<commit_before>/*
 * Copyright (c) 2016, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "application_manager/commands/hmi/sdl_activate_app_request.h"
#include "application_manager/state_controller.h"
#include "application_manager/message_helper.h"

namespace application_manager {

namespace commands {

SDLActivateAppRequest::SDLActivateAppRequest(
    const MessageSharedPtr& message, ApplicationManager& application_manager)
    : RequestFromHMI(message, application_manager) {}

SDLActivateAppRequest::~SDLActivateAppRequest() {}

void SDLActivateAppRequest::Run() {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace hmi_apis::FunctionID;
  using namespace hmi_apis::Common_Result;

  const uint32_t application_id = app_id();

  ApplicationConstSharedPtr app =
      application_manager_.application(application_id);

  if (!app) {
    LOG4CXX_ERROR(
        logger_,
        "Can't find application within regular apps: " << application_id);
    return;
  }

  DevicesApps devices_apps = FindAllAppOnParticularDevice(app->device());
  if (!devices_apps.first && devices_apps.second.empty()) {
    LOG4CXX_ERROR(logger_,
                  "Can't find regular foreground app with the same "
                  "connection id:"
                      << app->device());
    SendResponse(false, correlation_id(), SDL_ActivateApp, NO_APPS_REGISTERED);
    return;
  }

  if (!app->IsRegistered()) {
    if (devices_apps.first) {
      MessageHelper::SendLaunchApp(devices_apps.first->app_id(),
                                   app->SchemaUrl(),
                                   app->PackageName(),
                                   application_manager_);
    } else {
      std::vector<ApplicationSharedPtr>::const_iterator it =
          devices_apps.second.begin();
      for (; it != devices_apps.second.end(); ++it) {
        MessageHelper::SendLaunchApp((*it)->app_id(),
                                     app->SchemaUrl(),
                                     app->PackageName(),
                                     application_manager_);
      }
    }
    subscribe_on_event(BasicCommunication_OnAppRegistered);
  } else {
    if (devices_apps.first) {
      MessageHelper::SendLaunchApp(devices_apps.first->app_id(),
                                   app->SchemaUrl(),
                                   app->PackageName(),
                                   application_manager_);
    } else {
      const uint32_t application_id = app_id();
      application_manager_.GetPolicyHandler().OnActivateApp(application_id,
                                                            correlation_id());
    }
  }
}

void SDLActivateAppRequest::onTimeOut() {
  using namespace hmi_apis::FunctionID;
  using namespace hmi_apis::Common_Result;
  using namespace application_manager;
  unsubscribe_from_event(BasicCommunication_OnAppRegistered);
  SendResponse(
      false, correlation_id(), SDL_ActivateApp, APPLICATION_NOT_REGISTERED);
}

void SDLActivateAppRequest::on_event(const event_engine::Event& event) {
  using namespace hmi_apis::FunctionID;
  if (event.id() != BasicCommunication_OnAppRegistered) {
    return;
  }
  unsubscribe_from_event(BasicCommunication_OnAppRegistered);

  // Have to use HMI app id from event, since HMI app id from original request
  // message will be changed after app, initially requested for launch via
  // SDL.ActivateApp, will be registered
  const uint32_t hmi_application_id = hmi_app_id(event.smart_object());

  ApplicationSharedPtr app =
      application_manager_.application_by_hmi_app(hmi_application_id);
  if (!app) {
    LOG4CXX_ERROR(
        logger_, "Application not found by HMI app id: " << hmi_application_id);
    return;
  }
  application_manager_.GetPolicyHandler().OnActivateApp(app->app_id(),
                                                        correlation_id());
}

uint32_t SDLActivateAppRequest::app_id() const {
  if ((*message_).keyExists(strings::msg_params)) {
    if ((*message_)[strings::msg_params].keyExists(strings::app_id)) {
      return (*message_)[strings::msg_params][strings::app_id].asUInt();
    }
  }
  LOG4CXX_DEBUG(logger_, "app_id section is absent in the message.");
  return 0;
}

uint32_t SDLActivateAppRequest::hmi_app_id(
    const smart_objects::SmartObject& so) const {
  if (so.keyExists(strings::params)) {
    if (so[strings::msg_params].keyExists(strings::application)) {
      if (so[strings::msg_params][strings::application].keyExists(
              strings::app_id)) {
        return so[strings::msg_params][strings::application][strings::app_id]
            .asUInt();
      }
    }
  }
  LOG4CXX_DEBUG(logger_, "Can't find app_id section is absent in the message.");
  return 0;
}

DevicesApps SDLActivateAppRequest::FindAllAppOnParticularDevice(
    const connection_handler::DeviceHandle handle) {
  DevicesApps apps;
  const ApplicationSet app_list = application_manager_.applications().GetData();

  ApplicationSetIt it = app_list.begin();
  ApplicationSetIt it_end = app_list.end();

  for (; it != it_end; ++it) {
    if (handle == (*it)->device()) {
      if ((*it)->is_foreground()) {
        apps.first = *it;
      }
      apps.second.push_back(*it);
    }
  }
  return apps;
}

}  // namespace commands
}  // namespace application_manager
<commit_msg>Fixes LAUNCH_APP flow<commit_after>/*
 * Copyright (c) 2016, Ford Motor Company
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following
 * disclaimer in the documentation and/or other materials provided with the
 * distribution.
 *
 * Neither the name of the Ford Motor Company nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "application_manager/commands/hmi/sdl_activate_app_request.h"
#include "application_manager/state_controller.h"
#include "application_manager/message_helper.h"

namespace application_manager {

namespace commands {

SDLActivateAppRequest::SDLActivateAppRequest(
    const MessageSharedPtr& message, ApplicationManager& application_manager)
    : RequestFromHMI(message, application_manager) {}

SDLActivateAppRequest::~SDLActivateAppRequest() {}

void SDLActivateAppRequest::Run() {
  LOG4CXX_AUTO_TRACE(logger_);
  using namespace hmi_apis::FunctionID;
  using namespace hmi_apis::Common_Result;

  const uint32_t application_id = app_id();

  ApplicationConstSharedPtr app =
      application_manager_.application(application_id);

  if (!app) {
    LOG4CXX_ERROR(
        logger_,
        "Can't find application within regular apps: " << application_id);

    // Here is the hack - in fact SDL gets hmi_app_id in appID field and
    // replaces it with connection_key only for normally registered apps, but
    // for apps_to_be_registered (waiting) it keeps original value (hmi_app_id)
    // so method does lookup for hmi_app_id
    app = application_manager_.app_to_be_registered(application_id);

    if (!app) {
      LOG4CXX_WARN(
          logger_,
          "Can't find application within waiting apps: " << application_id);
      return;
    }
  }

  if (app->IsRegistered()) {
    application_manager_.GetPolicyHandler().OnActivateApp(application_id,
                                                          correlation_id());
    return;
  }

  DevicesApps devices_apps = FindAllAppOnParticularDevice(app->device());
  if (!devices_apps.first && devices_apps.second.empty()) {
    LOG4CXX_ERROR(logger_,
                  "Can't find regular foreground app with the same "
                  "connection id:"
                      << app->device());
    SendResponse(false, correlation_id(), SDL_ActivateApp, NO_APPS_REGISTERED);
    return;
  }

  if (devices_apps.first) {
    MessageHelper::SendLaunchApp(devices_apps.first->app_id(),
                                 app->SchemaUrl(),
                                 app->PackageName(),
                                 application_manager_);
  } else {
    std::vector<ApplicationSharedPtr>::const_iterator it =
        devices_apps.second.begin();
    for (; it != devices_apps.second.end(); ++it) {
      MessageHelper::SendLaunchApp((*it)->app_id(),
                                   app->SchemaUrl(),
                                   app->PackageName(),
                                   application_manager_);
    }
    subscribe_on_event(BasicCommunication_OnAppRegistered);
    return;
  }
}

void SDLActivateAppRequest::onTimeOut() {
  using namespace hmi_apis::FunctionID;
  using namespace hmi_apis::Common_Result;
  using namespace application_manager;
  unsubscribe_from_event(BasicCommunication_OnAppRegistered);
  SendResponse(
      false, correlation_id(), SDL_ActivateApp, APPLICATION_NOT_REGISTERED);
}

void SDLActivateAppRequest::on_event(const event_engine::Event& event) {
  using namespace hmi_apis::FunctionID;
  if (event.id() != BasicCommunication_OnAppRegistered) {
    return;
  }
  unsubscribe_from_event(BasicCommunication_OnAppRegistered);

  // Have to use HMI app id from event, since HMI app id from original request
  // message will be changed after app, initially requested for launch via
  // SDL.ActivateApp, will be registered
  const uint32_t hmi_application_id = hmi_app_id(event.smart_object());

  ApplicationSharedPtr app =
      application_manager_.application_by_hmi_app(hmi_application_id);
  if (!app) {
    LOG4CXX_ERROR(
        logger_, "Application not found by HMI app id: " << hmi_application_id);
    return;
  }
  application_manager_.GetPolicyHandler().OnActivateApp(app->app_id(),
                                                        correlation_id());
}

uint32_t SDLActivateAppRequest::app_id() const {
  if ((*message_).keyExists(strings::msg_params)) {
    if ((*message_)[strings::msg_params].keyExists(strings::app_id)) {
      return (*message_)[strings::msg_params][strings::app_id].asUInt();
    }
  }
  LOG4CXX_DEBUG(logger_, "app_id section is absent in the message.");
  return 0;
}

uint32_t SDLActivateAppRequest::hmi_app_id(
    const smart_objects::SmartObject& so) const {
  if (so.keyExists(strings::params)) {
    if (so[strings::msg_params].keyExists(strings::application)) {
      if (so[strings::msg_params][strings::application].keyExists(
              strings::app_id)) {
        return so[strings::msg_params][strings::application][strings::app_id]
            .asUInt();
      }
    }
  }
  LOG4CXX_DEBUG(logger_, "Can't find app_id section is absent in the message.");
  return 0;
}

DevicesApps SDLActivateAppRequest::FindAllAppOnParticularDevice(
    const connection_handler::DeviceHandle handle) {
  DevicesApps apps;
  const ApplicationSet app_list = application_manager_.applications().GetData();

  ApplicationSetIt it = app_list.begin();
  ApplicationSetIt it_end = app_list.end();

  for (; it != it_end; ++it) {
    if (handle == (*it)->device()) {
      if ((*it)->is_foreground()) {
        apps.first = *it;
      }
      apps.second.push_back(*it);
    }
  }
  return apps;
}

}  // namespace commands
}  // namespace application_manager
<|endoftext|>


<commit_before>#if defined(_MSC_VER)
	#include "stdafx.h"
#endif
#include "UnitTests.h"
#include "NULLC/nullc.h"
#include "NULLC/nullc_debug.h"
// Check that remote debug module compiles correctly
#if defined(_MSC_VER)
	#include "NULLC/nullc_remote.h"
#endif

#include "NULLC/ParseClass.h"

#include "NULLC/includes/file.h"
#include "NULLC/includes/math.h"
#include "NULLC/includes/vector.h"
#include "NULLC/includes/random.h"
#include "NULLC/includes/dynamic.h"
#include "NULLC/includes/gc.h"
#include "NULLC/includes/time.h"

#include "NULLC/includes/canvas.h"
#include "NULLC/includes/window.h"
#include "NULLC/includes/io.h"

#include "NULLC/includes/pugi.h"

#include "tests/TestBase.h"
#include "tests/TestSpeed.h"
#include "tests/TestCompileFail.h"
#include "tests/TestParseFail.h"
#include "tests/TestInterface.h"

#pragma warning(disable: 4127)

FILE *allocLog = NULL;
void* testAlloc(size_t size)
{
	if(!allocLog)
		allocLog = fopen("testAlloc.txt", "wb");
	static size_t overall = 0;
	static int allocs = 0;
	overall += size;
	allocs++;
	fprintf(allocLog, "%d Alloc of %u bytes (Total %u)\r\n", allocs, (unsigned int)size, (unsigned int)overall);
	fflush(allocLog);
	return malloc(size);
}
void testDealloc(void* ptr)
{
	free(ptr);
}

nullres CompileFile(const char* fileName)
{
	char content[64 * 1024];

	FILE *euler = fopen(fileName, "rb");
	fseek(euler, 0, SEEK_END);
	unsigned int textSize = ftell(euler);
	assert(textSize < 64 * 1024);
	fseek(euler, 0, SEEK_SET);
	fread(content, 1, textSize, euler);
	content[textSize] = 0;
	fclose(euler);

	return nullcCompile(content);
}

void	RunTests(bool verbose)
{
	Tests::messageVerbose = verbose;

	// Extra tests

	// Safe sprintf test
	{
		testsCount[3]++;

		char buf[8];
		char *pos = buf + SafeSprintf(buf, 8, "this ");
		pos += SafeSprintf(pos, 8 - int(pos - buf), "string is too long");
		if(memcmp(buf, "this st", 8) != 0)
			printf("Safe sprintf test failed: string is incorrect\n");
		else if(pos != buf + 8)
			printf("Safe sprintf test failed: iterator is incorrect\n");
		else
			testsPassed[3]++;
	}

/*
	unsigned int tStart = clock();
	for(unsigned int i = 0; i < 10000; i++)
	{
		nullcInit("Modules\\");
		nullcTerminate();
	}
	printf("Finished in %d\r\n", clock() - tStart);
*/

	// Init NULLC
	nullcInit(MODULE_PATH);
	//nullcInitCustomAlloc(testAlloc, testDealloc, "Modules\\");
	//nullcSetFileReadHandler(TestFileLoad);

	nullcInitTypeinfoModule();
	nullcInitFileModule();
	nullcInitMathModule();
	nullcInitVectorModule();
	nullcInitRandomModule();
	nullcInitDynamicModule();
	nullcInitGCModule();

	nullcInitIOModule();
	nullcInitCanvasModule();

#if defined(_MSC_VER)
	nullcInitWindowModule();
#endif

	/*
	//SpeedTestFile("test_document.nc");
	//SpeedTestFile("shapes.nc");
	//SpeedTestFile("raytrace.nc");
	//SpeedTestFile("blob.nc");
	return;*/

	RunInterfaceTests();

#ifdef NULLC_ENABLE_C_TRANSLATION
	nullres bRes = CompileFile("Modules/std/math.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_math.cpp", "__init_std_math_nc");

	bRes = CompileFile("Modules/std/typeinfo.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_typeinfo.cpp", "__init_std_typeinfo_nc");

	bRes = CompileFile("Modules/std/file.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_file.cpp", "__init_std_file_nc");

	bRes = CompileFile("Modules/std/vector.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_vector.cpp", "__init_std_vector_nc");

	bRes = nullcCompile("import std.math; float4 a; a.x = 2;");
	assert(bRes);
	nullcTranslateToC("test_a.cpp", "__init_test_a_nc");

	bRes = nullcCompile("char[] arr2 = \" world\";{ int r = 5; }");
	assert(bRes);
	nullcTranslateToC("test_importhide.cpp", "__init_test_importhide_nc");

	bRes = nullcCompile("int func(int a, b = 6){ return a * b; }");
	assert(bRes);
	nullcTranslateToC("test_defargs.cpp", "__init_test_defargs_nc");

	bRes = nullcCompile("int func(int a, b = 6){ return a * b; } int func(int d, c, a, b = 4){ return d * c + a + b; }");
	assert(bRes);
	nullcTranslateToC("test_defargs2.cpp", "__init_test_defargs2_nc");

	bRes = nullcCompile("class Test{ int func(int a, b = 6){ return a * b; } }");
	assert(bRes);
	nullcTranslateToC("test_defargs3.cpp", "__init_test_defargs3_nc");

	bRes = nullcCompile("class Test{ int func(int a, b = 6); }");
	assert(bRes);
	nullcTranslateToC("test_defargs4.cpp", "__init_test_defargs4_nc");

	bRes = nullcCompile("int foo(int x, char[] a = \"xx\", int y = 0){return x + a[0] + a[1];}");
	assert(bRes);
	nullcTranslateToC("test_defargs5.cpp", "__init_test_defargs5_nc");

	bRes = nullcCompile("int x = 5; int foo(auto ref a = &x){return int(a);}");
	assert(bRes);
	nullcTranslateToC("test_defargs6.cpp", "__init_test_defargs6_nc");

	bRes = nullcCompile("int CheckAlignment(auto ref ptr, int alignment);");
	assert(bRes);
	nullcTranslateToC("test_alignment.cpp", "__init_test_alignment_nc");

	bRes = CompileFile("Modules/std/list.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_list.cpp", "__init_std_list_nc");

	bRes = CompileFile("Modules/std/range.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_range.cpp", "__init_std_range_nc");

	bRes = CompileFile("Modules/std/gc.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_gc.cpp", "__init_std_gc_nc");

	bRes = CompileFile("Modules/std/dynamic.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_dynamic.cpp", "__init_std_dynamic_nc");

	bRes = CompileFile("Modules/std/io.nc");
	assert(bRes);
	nullcTranslateToC("NULLC\\translation\\std_io.cpp", "__init_std_io_nc");
#endif

	RunCompileFailTests();
	RunParseFailTests();

	TestQueue queue;
	queue.RunTests();

	// Conclusion
	printf("VM passed %d of %d tests\r\n", testsPassed[0], testsCount[0]);
#ifdef NULLC_BUILD_X86_JIT
	printf("X86 passed %d of %d tests\r\n", testsPassed[1], testsCount[1]);
#else
	testsPassed[1] = 0;
	testsCount[1] = 0;
#endif
#ifdef NULLC_LLVM_SUPPORT
	printf("LLVM passed %d of %d tests\r\n", testsPassed[2], testsCount[2]);
#else
	testsPassed[2] = 0;
	testsCount[2] = 0;
#endif
	printf("Failure tests: passed %d of %d tests\r\n", testsPassed[TEST_FAILURE_INDEX], testsCount[TEST_FAILURE_INDEX]);
	printf("Extra tests: passed %d of %d tests\r\n", testsPassed[TEST_EXTRA_INDEX], testsCount[TEST_EXTRA_INDEX]);
#ifdef NULLC_ENABLE_C_TRANSLATION
	printf("Translation tests: passed %d of %d tests\r\n", testsPassed[TEST_TRANSLATION_INDEX], testsCount[TEST_TRANSLATION_INDEX]);
#endif
	unsigned allTests = 0;
	unsigned allPassed = 0;
	for(unsigned i = 0; i < 6; i++)
	{
		allTests += testsCount[i];
		allPassed += testsPassed[i];
	}
	printf("Passed %d of %d tests\r\n", allPassed, allTests);

	printf("Compilation time: %f\r\n", Tests::timeCompile);
	printf("Get listing time: %f\r\n", Tests::timeGetListing);
	printf("Get bytecode time: %f\r\n", Tests::timeGetBytecode);
	printf("Clean time: %f\r\n", Tests::timeClean);
	printf("Link time: %f\r\n", Tests::timeLinkCode);
	printf("Run time: %f\r\n", Tests::timeRun);

	RunSpeedTests();

	// Terminate NULLC
	nullcTerminate();
}
<commit_msg>tests: standard library and test module translation to C now report a text error instead of assertion if compilation failed.<commit_after>#if defined(_MSC_VER)
	#include "stdafx.h"
#endif
#include "UnitTests.h"
#include "NULLC/nullc.h"
#include "NULLC/nullc_debug.h"
// Check that remote debug module compiles correctly
#if defined(_MSC_VER)
	#include "NULLC/nullc_remote.h"
#endif

#include "NULLC/ParseClass.h"

#include "NULLC/includes/file.h"
#include "NULLC/includes/math.h"
#include "NULLC/includes/vector.h"
#include "NULLC/includes/random.h"
#include "NULLC/includes/dynamic.h"
#include "NULLC/includes/gc.h"
#include "NULLC/includes/time.h"

#include "NULLC/includes/canvas.h"
#include "NULLC/includes/window.h"
#include "NULLC/includes/io.h"

#include "NULLC/includes/pugi.h"

#include "tests/TestBase.h"
#include "tests/TestSpeed.h"
#include "tests/TestCompileFail.h"
#include "tests/TestParseFail.h"
#include "tests/TestInterface.h"

#pragma warning(disable: 4127)

FILE *allocLog = NULL;
void* testAlloc(size_t size)
{
	if(!allocLog)
		allocLog = fopen("testAlloc.txt", "wb");
	static size_t overall = 0;
	static int allocs = 0;
	overall += size;
	allocs++;
	fprintf(allocLog, "%d Alloc of %u bytes (Total %u)\r\n", allocs, (unsigned int)size, (unsigned int)overall);
	fflush(allocLog);
	return malloc(size);
}
void testDealloc(void* ptr)
{
	free(ptr);
}

nullres CompileFile(const char* fileName)
{
	char content[64 * 1024];

	FILE *euler = fopen(fileName, "rb");
	fseek(euler, 0, SEEK_END);
	unsigned int textSize = ftell(euler);
	assert(textSize < 64 * 1024);
	fseek(euler, 0, SEEK_SET);
	fread(content, 1, textSize, euler);
	content[textSize] = 0;
	fclose(euler);

	return nullcCompile(content);
}

void	RunTests(bool verbose)
{
	Tests::messageVerbose = verbose;

	// Extra tests

	// Safe sprintf test
	{
		testsCount[3]++;

		char buf[8];
		char *pos = buf + SafeSprintf(buf, 8, "this ");
		pos += SafeSprintf(pos, 8 - int(pos - buf), "string is too long");
		if(memcmp(buf, "this st", 8) != 0)
			printf("Safe sprintf test failed: string is incorrect\n");
		else if(pos != buf + 8)
			printf("Safe sprintf test failed: iterator is incorrect\n");
		else
			testsPassed[3]++;
	}

/*
	unsigned int tStart = clock();
	for(unsigned int i = 0; i < 10000; i++)
	{
		nullcInit("Modules\\");
		nullcTerminate();
	}
	printf("Finished in %d\r\n", clock() - tStart);
*/

	// Init NULLC
	nullcInit(MODULE_PATH);
	//nullcInitCustomAlloc(testAlloc, testDealloc, "Modules\\");
	//nullcSetFileReadHandler(TestFileLoad);

	nullcInitTypeinfoModule();
	nullcInitFileModule();
	nullcInitMathModule();
	nullcInitVectorModule();
	nullcInitRandomModule();
	nullcInitDynamicModule();
	nullcInitGCModule();

	nullcInitIOModule();
	nullcInitCanvasModule();

#if defined(_MSC_VER)
	nullcInitWindowModule();
#endif

	/*
	//SpeedTestFile("test_document.nc");
	//SpeedTestFile("shapes.nc");
	//SpeedTestFile("raytrace.nc");
	//SpeedTestFile("blob.nc");
	return;*/

	RunInterfaceTests();

#ifdef NULLC_ENABLE_C_TRANSLATION
	if(!CompileFile("Modules/std/math.nc"))
		printf("ERROR: failed to compile std.math for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_math.cpp", "__init_std_math_nc");

	if(!CompileFile("Modules/std/typeinfo.nc"))
		printf("ERROR: failed to compile std.typeinfo for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_typeinfo.cpp", "__init_std_typeinfo_nc");

	if(!CompileFile("Modules/std/file.nc"))
		printf("ERROR: failed to compile std.file for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_file.cpp", "__init_std_file_nc");

	if(!CompileFile("Modules/std/vector.nc"))
		printf("ERROR: failed to compile std.vector for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_vector.cpp", "__init_std_vector_nc");

	if(!nullcCompile("import std.math; float4 a; a.x = 2;"))
		printf("ERROR: failed to compile test_a for translation\n");
	nullcTranslateToC("test_a.cpp", "__init_test_a_nc");

	if(!nullcCompile("char[] arr2 = \" world\";{ int r = 5; }"))
		printf("ERROR: failed to compile test_importhide for translation\n");
	nullcTranslateToC("test_importhide.cpp", "__init_test_importhide_nc");

	if(!nullcCompile("int func(int a, b = 6){ return a * b; }"))
		printf("ERROR: failed to compile test_defargs for translation\n");
	nullcTranslateToC("test_defargs.cpp", "__init_test_defargs_nc");

	if(!nullcCompile("int func(int a, b = 6){ return a * b; } int func(int d, c, a, b = 4){ return d * c + a + b; }"))
		printf("ERROR: failed to compile test_defargs2 for translation\n");
	nullcTranslateToC("test_defargs2.cpp", "__init_test_defargs2_nc");

	if(!nullcCompile("class Test{ int func(int a, b = 6){ return a * b; } }"))
		printf("ERROR: failed to compile test_defargs3 for translation\n");
	nullcTranslateToC("test_defargs3.cpp", "__init_test_defargs3_nc");

	if(!nullcCompile("class Test{ int func(int a, b = 6); }"))
		printf("ERROR: failed to compile test_defargs4 for translation\n");
	nullcTranslateToC("test_defargs4.cpp", "__init_test_defargs4_nc");

	if(!nullcCompile("int foo(int x, char[] a = \"xx\", int y = 0){return x + a[0] + a[1];}"))
		printf("ERROR: failed to compile test_defargs5 for translation\n");
	nullcTranslateToC("test_defargs5.cpp", "__init_test_defargs5_nc");

	if(!nullcCompile("int x = 5; int foo(auto ref a = &x){return int(a);}"))
		printf("ERROR: failed to compile test_defargs6 for translation\n");
	nullcTranslateToC("test_defargs6.cpp", "__init_test_defargs6_nc");

	if(!nullcCompile("int CheckAlignment(auto ref ptr, int alignment);"))
		printf("ERROR: failed to compile test_alignment for translation\n");
	nullcTranslateToC("test_alignment.cpp", "__init_test_alignment_nc");

	if(!CompileFile("Modules/std/list.nc"))
		printf("ERROR: failed to compile std.list for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_list.cpp", "__init_std_list_nc");

	if(!CompileFile("Modules/std/range.nc"))
		printf("ERROR: failed to compile std.range for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_range.cpp", "__init_std_range_nc");

	if(!CompileFile("Modules/std/gc.nc"))
		printf("ERROR: failed to compile std.gc for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_gc.cpp", "__init_std_gc_nc");

	if(!CompileFile("Modules/std/dynamic.nc"))
		printf("ERROR: failed to compile std.dynamic for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_dynamic.cpp", "__init_std_dynamic_nc");

	if(!CompileFile("Modules/std/io.nc"))
		printf("ERROR: failed to compile std.io for translation\n");
	nullcTranslateToC("NULLC\\translation\\std_io.cpp", "__init_std_io_nc");
#endif

	RunCompileFailTests();
	RunParseFailTests();

	TestQueue queue;
	queue.RunTests();

	// Conclusion
	printf("VM passed %d of %d tests\r\n", testsPassed[0], testsCount[0]);
#ifdef NULLC_BUILD_X86_JIT
	printf("X86 passed %d of %d tests\r\n", testsPassed[1], testsCount[1]);
#else
	testsPassed[1] = 0;
	testsCount[1] = 0;
#endif
#ifdef NULLC_LLVM_SUPPORT
	printf("LLVM passed %d of %d tests\r\n", testsPassed[2], testsCount[2]);
#else
	testsPassed[2] = 0;
	testsCount[2] = 0;
#endif
	printf("Failure tests: passed %d of %d tests\r\n", testsPassed[TEST_FAILURE_INDEX], testsCount[TEST_FAILURE_INDEX]);
	printf("Extra tests: passed %d of %d tests\r\n", testsPassed[TEST_EXTRA_INDEX], testsCount[TEST_EXTRA_INDEX]);
#ifdef NULLC_ENABLE_C_TRANSLATION
	printf("Translation tests: passed %d of %d tests\r\n", testsPassed[TEST_TRANSLATION_INDEX], testsCount[TEST_TRANSLATION_INDEX]);
#endif
	unsigned allTests = 0;
	unsigned allPassed = 0;
	for(unsigned i = 0; i < 6; i++)
	{
		allTests += testsCount[i];
		allPassed += testsPassed[i];
	}
	printf("Passed %d of %d tests\r\n", allPassed, allTests);

	printf("Compilation time: %f\r\n", Tests::timeCompile);
	printf("Get listing time: %f\r\n", Tests::timeGetListing);
	printf("Get bytecode time: %f\r\n", Tests::timeGetBytecode);
	printf("Clean time: %f\r\n", Tests::timeClean);
	printf("Link time: %f\r\n", Tests::timeLinkCode);
	printf("Run time: %f\r\n", Tests::timeRun);

	RunSpeedTests();

	// Terminate NULLC
	nullcTerminate();
}
<|endoftext|>


<commit_before>//=============================================================================
// ■ main.cpp
//-----------------------------------------------------------------------------
//   VMGS的主程序。
//=============================================================================

#include "VMGS.hpp"

namespace VM76 {
	Shaders* shader_textured = NULL;
	Shaders* shader_basic = NULL;
	Res::Texture* tile_texture = NULL;

	Cube* block_pointer;
	TiledMap* map;

	Axis* axe;

	Object* obj = new Object();

	int map_count = 0;

	void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
		#define PRESS(n) key == n && action == GLFW_PRESS
		if (PRESS(GLFW_KEY_A)) obj->move(glm::vec3(-0.5, 0.0, 0.0));
		if (PRESS(GLFW_KEY_D)) obj->move(glm::vec3(0.5, 0.0, 0.0));
		if (PRESS(GLFW_KEY_W)) obj->move(glm::vec3(0.0, 0.0, -0.5));
		if (PRESS(GLFW_KEY_S)) obj->move(glm::vec3(0.0, 0.0, 0.5));
		if (PRESS(GLFW_KEY_UP)) obj->move(glm::vec3(0.0, 0.5, 0.0));
		if (PRESS(GLFW_KEY_DOWN)) obj->move(glm::vec3(0.0, -0.5, 0.0));

		if (PRESS(GLFW_KEY_SPACE)) {
			map->tiles[map->calcTileIndex(obj->pos * 2.0f)].tid = 2;
			map->bake_tiles();
		}
		#undef PRESS
	}

	void loop() {
		for (;;) {
			::main_draw_start();
			update_control();

			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

			shader_textured->use();

			// Setup uniforms
			shader_textured->set_float("brightness", VMDE->state.brightness);

			shader_textured->ProjectionView(projection, view);
			map->render();

			// Setup uniforms
			shader_basic->use();
			shader_textured->ProjectionView(projection, view);
			block_pointer->mat[0] = obj->transform();
			block_pointer->update_instance(1);
			block_pointer->render();

			axe->render();

			::main_draw_end();
			if (VMDE->done) break;
		}
	}

	void init_textures() {
		shader_textured->set_texture("colortex0", tile_texture, 0);
	}

	void start_game() {
		// 先设好事件回调然后再启动引擎，最大地避免段错误
		on_terminate = terminate;
		::init_engine(860, 540, "VM / 76");
		init_control();

		tile_texture = new Res::Texture("../Media/terrain.png");

		shader_textured = Shaders::CreateFromFile("../Media/shaders/gbuffers_textured.vsh", "../Media/shaders/gbuffers_textured.fsh");
		shader_basic = Shaders::CreateFromFile("../Media/shaders/gbuffers_basic.vsh", "../Media/shaders/gbuffers_basic.fsh");

		projection = glm::perspective(1.3f, float(VMDE->width) / float(VMDE->height), 0.1f, 1000.0f);
		view = glm::lookAt(glm::vec3(0.0, 2.6, 0.0), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));

		// GL settings initialize
		glFrontFace(GL_CCW);
		glEnable(GL_CULL_FACE);

		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LEQUAL);

		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glDepthRange(0.0f, 1.0f);
		glClearDepth(1.0f);
		glDepthMask(GL_TRUE);

		init_textures();

		block_pointer = new Cube(1);
		axe = new Axis();
		map = new TiledMap(16, 16, 16);
		block_pointer->obj->data.mat_c = 1;
		glfwSetKeyCallback(window, key_callback);

		loop();
	}

	void terminate() {
		log("starting to terminate");
		terminate_engine();
		VMDE_Dispose(tile_texture);
		VMDE_Dispose(block_pointer);
		VMDE_Dispose(map);
		log("terminated successfully");
	}
}

int main() {
	log("Hello! This is VM76. Nice to meet you!");
	VM76::start_game();
}
<commit_msg>放置方块声效<commit_after>//=============================================================================
// ■ main.cpp
//-----------------------------------------------------------------------------
//   VMGS的主程序。
//=============================================================================

#include "VMGS.hpp"

namespace VM76 {
	Shaders* shader_textured = NULL;
	Shaders* shader_basic = NULL;
	Res::Texture* tile_texture = NULL;

	Cube* block_pointer;
	TiledMap* map;

	Axis* axe;

	Object* obj = new Object();

	int map_count = 0;

	void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
		#define PRESS(n) key == n && action == GLFW_PRESS
		if (PRESS(GLFW_KEY_A)) obj->move(glm::vec3(-0.5, 0.0, 0.0));
		if (PRESS(GLFW_KEY_D)) obj->move(glm::vec3(0.5, 0.0, 0.0));
		if (PRESS(GLFW_KEY_W)) obj->move(glm::vec3(0.0, 0.0, -0.5));
		if (PRESS(GLFW_KEY_S)) obj->move(glm::vec3(0.0, 0.0, 0.5));
		if (PRESS(GLFW_KEY_UP)) obj->move(glm::vec3(0.0, 0.5, 0.0));
		if (PRESS(GLFW_KEY_DOWN)) obj->move(glm::vec3(0.0, -0.5, 0.0));

		if (PRESS(GLFW_KEY_SPACE)) {
			Audio::play_sound("../Media/soft-ping.ogg", false);
			map->tiles[map->calcTileIndex(obj->pos * 2.0f)].tid = 2;
			map->bake_tiles();
		}
		#undef PRESS
	}

	void loop() {
		for (;;) {
			::main_draw_start();
			update_control();

			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

			shader_textured->use();

			// Setup uniforms
			shader_textured->set_float("brightness", VMDE->state.brightness);

			shader_textured->ProjectionView(projection, view);
			map->render();

			// Setup uniforms
			shader_basic->use();
			shader_textured->ProjectionView(projection, view);
			block_pointer->mat[0] = obj->transform();
			block_pointer->update_instance(1);
			block_pointer->render();

			axe->render();

			::main_draw_end();
			if (VMDE->done) break;
		}
	}

	void init_textures() {
		shader_textured->set_texture("colortex0", tile_texture, 0);
	}

	void start_game() {
		// 先设好事件回调然后再启动引擎，最大地避免段错误
		on_terminate = terminate;
		::init_engine(860, 540, "VM / 76");
		init_control();

		tile_texture = new Res::Texture("../Media/terrain.png");

		shader_textured = Shaders::CreateFromFile("../Media/shaders/gbuffers_textured.vsh", "../Media/shaders/gbuffers_textured.fsh");
		shader_basic = Shaders::CreateFromFile("../Media/shaders/gbuffers_basic.vsh", "../Media/shaders/gbuffers_basic.fsh");

		projection = glm::perspective(1.3f, float(VMDE->width) / float(VMDE->height), 0.1f, 1000.0f);
		view = glm::lookAt(glm::vec3(0.0, 2.6, 0.0), glm::vec3(0.0, 0.0, 0.0), glm::vec3(0.0, 1.0, 0.0));

		// GL settings initialize
		glFrontFace(GL_CCW);
		glEnable(GL_CULL_FACE);

		glEnable(GL_DEPTH_TEST);
		glDepthFunc(GL_LEQUAL);

		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glDepthRange(0.0f, 1.0f);
		glClearDepth(1.0f);
		glDepthMask(GL_TRUE);

		init_textures();

		block_pointer = new Cube(1);
		axe = new Axis();
		map = new TiledMap(16, 16, 16);
		block_pointer->obj->data.mat_c = 1;
		glfwSetKeyCallback(window, key_callback);

		loop();
	}

	void terminate() {
		log("starting to terminate");
		terminate_engine();
		VMDE_Dispose(tile_texture);
		VMDE_Dispose(block_pointer);
		VMDE_Dispose(map);
		log("terminated successfully");
	}
}

int main() {
	log("Hello! This is VM76. Nice to meet you!");
	VM76::start_game();
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "properties.h"

#include "utils.h"

#include <iostream>
#include <iomanip>
#include <memory>

#include <gst/gst.h>
#include "tcamprop.h"

#include "tcam.h"

#include "general.h"

using namespace tcam;

static const size_t name_width = 40;

void print_properties (const std::string& serial)
{
    GstElement* source = gst_element_factory_make("tcamsrc", "source");

    if (!source)
    {
        std::cerr << "Unable to create source element." << std::endl;
        return;
    }

    if (!is_valid_device_serial(source, serial))
    {
        std::cerr << "Device with given serial does not exist." << std::endl;
        return;
    }

    std::string str;

    GValue val = {};
    g_value_init(&val, G_TYPE_STRING);
    g_value_set_static_string(&val, serial.c_str());

    g_object_set_property(G_OBJECT(source), "serial", &val);

    GSList* names = tcam_prop_get_tcam_property_names(TCAM_PROP(source));

    for (unsigned int i = 0; i < g_slist_length(names); ++i)
    {
        char* name = (char*)g_slist_nth(names, i)->data;

        GValue value = {};
        GValue min = {};
        GValue max = {};
        GValue default_value = {};
        GValue step_size = {};
        GValue type = {};
        GValue flags = {};
        GValue category = {};
        GValue group = {};

        gboolean ret = tcam_prop_get_tcam_property(TCAM_PROP(source),
                                                   name,
                                                   &value,
                                                   &min,
                                                   &max,
                                                   &default_value,
                                                   &step_size,
                                                   &type,
                                                   &flags,
                                                   &category,
                                                   &group);

        if (!ret)
        {
            printf("Could not query property '%s'\n", name);
            continue;
        }
        std::cout << std::left;

        const char* t = g_value_get_string(&type);
        if (strcmp(t, "integer") == 0)
        {
            std::cout << std::setw(name_width) << name
                      << "(int)"<< std::right
                      << " min=" << g_value_get_int(&min)
                      << " max=" << g_value_get_int(&max)
                      << " step=" << g_value_get_int(&step_size)
                      << " default=" << g_value_get_int(&default_value)
                      << " value=" << g_value_get_int(&default_value)
                      << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << std::endl;
        }
        else if (strcmp(t, "double") == 0)
        {
            std::cout << std::setw(name_width) << name
                      << "(double)"<< std::right
                      << " min=" << g_value_get_double(&min)
                      << " max=" << g_value_get_double(&max)
                      << " step=" << g_value_get_double(&step_size)
                      << " default=" << g_value_get_double(&default_value)
                      << " value=" << g_value_get_double(&value)
                      << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << std::endl;
        }
        else if (strcmp(t, "string") == 0)
        {
            printf("%s(string) value: %s default: %s  grouping %s %s\n",
                   name,
                   g_value_get_string(&value), g_value_get_string(&default_value),
                   g_value_get_string(&category), g_value_get_string(&group));
        }
        else if (strcmp(t, "enum") == 0)
        {
            GSList* entries = tcam_prop_get_tcam_menu_entries(TCAM_PROP(source), name);

            if (entries == NULL)
            {
                printf("%s returned no enumeration values.\n", name);
                continue;
            }

            std::cout << std::setw(name_width) << name
                      << "(enum) "
                      << " default="<< std::setw(6) << g_value_get_string(&default_value)
                      << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << "\n\t\t\t\t\t\tvalue=" << g_value_get_string(&value) << std::endl;
            for (unsigned int x = 0; x < g_slist_length(entries); ++x)
            {
                printf("\t\t\t\t\t\t\t %s\n", (const char*)g_slist_nth(entries, x)->data);
            }
        }
        else if (strcmp(t, "boolean") == 0)
        {
            std::cout << std::setw(name_width) << name
                      << "(bool)"
                      << " default=";
            if (g_value_get_boolean(&default_value))
            {
                std::cout << "true";
            }
            else
            {
                std::cout << "false";
            }
            std::cout << " value=";
            if (g_value_get_boolean(&value))
            {
                std::cout << "true";
            }
            else
            {
                std::cout << "false";
            }
            std::cout << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << std::endl;
        }
        else if (strcmp(t, "button") == 0)
        {
            std::cout << std::setw(name_width) << name
                      << "(button)"
                      << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << std::endl;
        }
        else
        {
            printf("Property '%s' has type '%s' .\n", name, t);
        }
    }

    g_slist_free(names);
    gst_object_unref(source);

}

void print_state_json (const std::string& serial)
{

    GstElement* source = gst_element_factory_make("tcamsrc", "source");

    if (!source)
    {
        std::cerr << "Unable to create source element." << std::endl;
        return;
    }

    if (!is_valid_device_serial(source, serial))
    {
        std::cerr << "Device with given serial does not exist." << std::endl;
        return;
    }

    GValue val = {};
    g_value_init(&val, G_TYPE_STRING);
    g_value_set_static_string(&val, serial.c_str());

    g_object_set_property(G_OBJECT(source), "serial", &val);

    gst_element_set_state(source, GST_STATE_READY);

    const char* state_str = nullptr;
    g_object_get(G_OBJECT(source), "state", &state_str, NULL);

    std::cout << state_str << std::endl;
    gst_element_set_state(source, GST_STATE_NULL);

    gst_object_unref(source);
}

void load_state_json_string (const std::string& serial, const std::string& json_str)
{
    GstElement* source = gst_element_factory_make("tcamsrc", "source");

    if (!source)
    {
        std::cerr << "Unable to create source element." << std::endl;
        return;
    }

    if (!is_valid_device_serial(source, serial))
    {
        std::cerr << "Device with given serial does not exist." << std::endl;
        return;
    }

    GValue val = {};
    g_value_init(&val, G_TYPE_STRING);
    g_value_set_static_string(&val, serial.c_str());

    g_object_set_property(G_OBJECT(source), "serial", &val);

    gst_element_set_state(source, GST_STATE_READY);

    g_object_set(G_OBJECT(source), "state", json_str.c_str(), NULL);
    gst_element_set_state(source, GST_STATE_NULL);

    gst_object_unref(source);
}
<commit_msg>tcam-ctrl: Fix int value display<commit_after>/*
 * Copyright 2014 The Imaging Source Europe GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "properties.h"

#include "utils.h"

#include <iostream>
#include <iomanip>
#include <memory>

#include <gst/gst.h>
#include "tcamprop.h"

#include "tcam.h"

#include "general.h"

using namespace tcam;

static const size_t name_width = 40;

void print_properties (const std::string& serial)
{
    GstElement* source = gst_element_factory_make("tcamsrc", "source");

    if (!source)
    {
        std::cerr << "Unable to create source element." << std::endl;
        return;
    }

    if (!is_valid_device_serial(source, serial))
    {
        std::cerr << "Device with given serial does not exist." << std::endl;
        return;
    }

    std::string str;

    GValue val = {};
    g_value_init(&val, G_TYPE_STRING);
    g_value_set_static_string(&val, serial.c_str());

    g_object_set_property(G_OBJECT(source), "serial", &val);

    GSList* names = tcam_prop_get_tcam_property_names(TCAM_PROP(source));

    for (unsigned int i = 0; i < g_slist_length(names); ++i)
    {
        char* name = (char*)g_slist_nth(names, i)->data;

        GValue value = {};
        GValue min = {};
        GValue max = {};
        GValue default_value = {};
        GValue step_size = {};
        GValue type = {};
        GValue flags = {};
        GValue category = {};
        GValue group = {};

        gboolean ret = tcam_prop_get_tcam_property(TCAM_PROP(source),
                                                   name,
                                                   &value,
                                                   &min,
                                                   &max,
                                                   &default_value,
                                                   &step_size,
                                                   &type,
                                                   &flags,
                                                   &category,
                                                   &group);

        if (!ret)
        {
            printf("Could not query property '%s'\n", name);
            continue;
        }
        std::cout << std::left;

        const char* t = g_value_get_string(&type);
        if (strcmp(t, "integer") == 0)
        {
            std::cout << std::setw(name_width) << name
                      << "(int)"<< std::right
                      << " min=" << g_value_get_int(&min)
                      << " max=" << g_value_get_int(&max)
                      << " step=" << g_value_get_int(&step_size)
                      << " default=" << g_value_get_int(&default_value)
                      << " value=" << g_value_get_int(&value)
                      << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << std::endl;
        }
        else if (strcmp(t, "double") == 0)
        {
            std::cout << std::setw(name_width) << name
                      << "(double)"<< std::right
                      << " min=" << g_value_get_double(&min)
                      << " max=" << g_value_get_double(&max)
                      << " step=" << g_value_get_double(&step_size)
                      << " default=" << g_value_get_double(&default_value)
                      << " value=" << g_value_get_double(&value)
                      << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << std::endl;
        }
        else if (strcmp(t, "string") == 0)
        {
            printf("%s(string) value: %s default: %s  grouping %s %s\n",
                   name,
                   g_value_get_string(&value), g_value_get_string(&default_value),
                   g_value_get_string(&category), g_value_get_string(&group));
        }
        else if (strcmp(t, "enum") == 0)
        {
            GSList* entries = tcam_prop_get_tcam_menu_entries(TCAM_PROP(source), name);

            if (entries == NULL)
            {
                printf("%s returned no enumeration values.\n", name);
                continue;
            }

            std::cout << std::setw(name_width) << name
                      << "(enum) "
                      << " default="<< std::setw(6) << g_value_get_string(&default_value)
                      << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << "\n\t\t\t\t\t\tvalue=" << g_value_get_string(&value) << std::endl;
            for (unsigned int x = 0; x < g_slist_length(entries); ++x)
            {
                printf("\t\t\t\t\t\t\t %s\n", (const char*)g_slist_nth(entries, x)->data);
            }
        }
        else if (strcmp(t, "boolean") == 0)
        {
            std::cout << std::setw(name_width) << name
                      << "(bool)"
                      << " default=";
            if (g_value_get_boolean(&default_value))
            {
                std::cout << "true";
            }
            else
            {
                std::cout << "false";
            }
            std::cout << " value=";
            if (g_value_get_boolean(&value))
            {
                std::cout << "true";
            }
            else
            {
                std::cout << "false";
            }
            std::cout << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << std::endl;
        }
        else if (strcmp(t, "button") == 0)
        {
            std::cout << std::setw(name_width) << name
                      << "(button)"
                      << " category=" << g_value_get_string(&category)
                      << " group=" << g_value_get_string(&group)
                      << std::endl;
        }
        else
        {
            printf("Property '%s' has type '%s' .\n", name, t);
        }
    }

    g_slist_free(names);
    gst_object_unref(source);

}

void print_state_json (const std::string& serial)
{

    GstElement* source = gst_element_factory_make("tcamsrc", "source");

    if (!source)
    {
        std::cerr << "Unable to create source element." << std::endl;
        return;
    }

    if (!is_valid_device_serial(source, serial))
    {
        std::cerr << "Device with given serial does not exist." << std::endl;
        return;
    }

    GValue val = {};
    g_value_init(&val, G_TYPE_STRING);
    g_value_set_static_string(&val, serial.c_str());

    g_object_set_property(G_OBJECT(source), "serial", &val);

    gst_element_set_state(source, GST_STATE_READY);

    const char* state_str = nullptr;
    g_object_get(G_OBJECT(source), "state", &state_str, NULL);

    std::cout << state_str << std::endl;
    gst_element_set_state(source, GST_STATE_NULL);

    gst_object_unref(source);
}

void load_state_json_string (const std::string& serial, const std::string& json_str)
{
    GstElement* source = gst_element_factory_make("tcamsrc", "source");

    if (!source)
    {
        std::cerr << "Unable to create source element." << std::endl;
        return;
    }

    if (!is_valid_device_serial(source, serial))
    {
        std::cerr << "Device with given serial does not exist." << std::endl;
        return;
    }

    GValue val = {};
    g_value_init(&val, G_TYPE_STRING);
    g_value_set_static_string(&val, serial.c_str());

    g_object_set_property(G_OBJECT(source), "serial", &val);

    gst_element_set_state(source, GST_STATE_READY);

    g_object_set(G_OBJECT(source), "state", json_str.c_str(), NULL);
    gst_element_set_state(source, GST_STATE_NULL);

    gst_object_unref(source);
}
<|endoftext|>


<commit_before>/*
 * MIT License
 *
 * Copyright (c) 2017 Kevin Kirchner
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * \file        libelfpp.cpp
 * \brief       Main source file for \p libelfpp
 * \author      Kevin Kirchner
 * \date        2017
 * \copyright   MIT LICENSE
 *
 * This source file is the main source file for \p libelfpp and implements the
 * library's public interface.
 */

#include "libelfpp/libelfpp.h"
#include "private_impl.h"
#include <cstring>
#include <iostream>

namespace libelfpp {

// Implementation of constructor
ELFFile::ELFFile(const std::string& filename) : Filename(filename) {
  std::ifstream Input(filename);
  if (!Input.good()) {
    throw std::runtime_error("File does not exist!");
  }

  unsigned char e_ident[EI_NIDENT];
  Input.seekg(0);
  Input.read(reinterpret_cast<char*>(&e_ident), sizeof(e_ident));

  // check if file is ELF file
  if (Input.gcount() != sizeof(e_ident) ||
      std::memcmp(e_ident, ELFMAG, std::strlen(ELFMAG)) != 0) {
    throw std::runtime_error("Invalid magic number!");
  }

  switch (e_ident[EI_CLASS]) {
  case ELFCLASS32:
    Is64Bit = false;
    break;
  case ELFCLASS64:
    Is64Bit = true;
    break;
  default:
    throw std::runtime_error("Invalid ELF file class!");
  }

  switch (e_ident[EI_DATA]) {
  case ELFDATA2LSB:
    IsLittleEndian = true;
    break;
  case ELFDATA2MSB:
    IsLittleEndian = false;
    break;
  default:
    throw std::runtime_error("Invalid ELF encoding!");
  }

  Converter = std::make_shared<EndianessConverter>(IsLittleEndian);

  if (Is64Bit) {
    FileHeader = std::make_shared<ELFHeaderImpl<Elf64_Ehdr>>(Converter, IsLittleEndian, Input);
  } else {
    FileHeader = std::make_shared<ELFHeaderImpl<Elf32_Ehdr>>(Converter, IsLittleEndian, Input);
  }

  loadSegmentsFromFile(Input);
  loadSectionsFromFile(Input);
  Input.close();
}

// Loads all segmetns from the file stream
Elf64_Half ELFFile::loadSegmentsFromFile(std::ifstream& stream) {
  Elf64_Half entrySize = FileHeader->getProgramHeaderSize();
  Elf64_Half segmentNumber = FileHeader->getProgramHeaderNumber();
  Elf64_Off offset = FileHeader->getProgramHeaderOffset();

  for (Elf64_Half iter = 0; iter < segmentNumber; ++iter) {
    std::shared_ptr<Segment> Seg;
    Elf64_Off baseOff, endOff, vBaseAddr, vEndAddr;

    if (Is64Bit) {
      Seg = std::make_shared<SegmentImpl<Elf64_Phdr>>(Converter);
    } else {
      Seg = std::make_shared<SegmentImpl<Elf32_Phdr>>(Converter);
    }
    Seg->loadSegment(stream, (std::streamoff) offset + iter * entrySize);
    Seg->setIndex(iter);
    Segments.push_back(Seg);

    // add associated sections
    baseOff = Seg->getOffset();
    endOff = baseOff + Seg->getFileSize();
    vBaseAddr = Seg->getVirtualAddress();
    vEndAddr = vBaseAddr + Seg->getMemorySize();

    for (const auto& Section : Sections) {
      if (Section->getFlags() & SHF_ALLOC) {
        if (vBaseAddr <= Section->getAddress() &&
            Section->getAddress() + Section->getSize() <= vEndAddr) {
          Seg->addSectionIndex(Section->getIndex());
        }
      } else {
        if (baseOff <= Section->getOffset() &&
            Section->getOffset() + Section->getSize() <= endOff) {
          Seg->addSectionIndex(Section->getIndex());
        }
      }
    }
  }

  return segmentNumber;
}

// Loads all sections from the file stream
Elf64_Half ELFFile::loadSectionsFromFile(std::ifstream& stream) {
  Elf64_Half entrySize = FileHeader->getSectionHeaderSize();
  Elf64_Half sectionNumber = FileHeader->getSectionHeaderNumber();
  Elf64_Off offset = FileHeader->getSectionHeaderOffset();

  for (Elf64_Half iter = 0; iter < sectionNumber; ++iter) {
    std::shared_ptr<Section> Sec;
    if (Is64Bit) {
      Sec = std::make_shared<SectionImpl<Elf64_Shdr>>(Converter);
    } else {
      Sec = std::make_shared<SectionImpl<Elf32_Shdr>>(Converter);
    }
    Sec->loadSection(stream, (std::streamoff) offset + iter * entrySize);
    Sec->setIndex(iter);
    Sections.push_back(Sec);

    if (Sec->getType() == SHT_DYNAMIC) {
      if (FileHeader->is64Bit()) {
        DynamicSec = DynamicSectionImpl<Elf64_Shdr, Elf64_Dyn>::fromSection(Sec);
      } else {
        DynamicSec = DynamicSectionImpl<Elf32_Shdr, Elf32_Dyn>::fromSection(Sec);
      }
    }
  }

  // get primary string section
  Elf64_Half StringIndex = FileHeader->getSectionHeaderStringTableIndex();
  if (StringIndex != SHN_UNDEF) {
    if (FileHeader->is64Bit()) {
      StrSection = StringSectionImpl<Elf64_Shdr>::fromSection(Sections[StringIndex]);
    } else {
      StrSection = StringSectionImpl<Elf32_Shdr>::fromSection(Sections[StringIndex]);
    }

    for (const auto& Sec : Sections) {
      Sec->setName(StrSection->getString(Sec->getNameStringOffset()));

      // get symbol sections in this loop, so we do not need to loop again
      if (Sec->getType() == SHT_DYNSYM || Sec->getType() == SHT_SYMTAB) {
        std::shared_ptr<SymbolSection> Sym;
        std::shared_ptr<StringSection> Str;
        if (FileHeader->is64Bit()) {
          Str = StringSectionImpl<Elf64_Shdr>::fromSection(Sections[Sec->getLink()]);
          Sym = SymbolSectionImpl<Elf64_Shdr, Elf64_Sym>::fromSection(Sec, Str);
        } else {

        }
        if (Sym)
          SymbolSections.push_back(Sym);
      }

      if (Sec->getType() == SHT_REL || Sec->getType() == SHT_RELA) {
        std::shared_ptr<RelocationSection> Reloc;
        std::shared_ptr<StringSection> Str;
        std::shared_ptr<SymbolSection> Sym;

        if (FileHeader->is64Bit()) {
          Str = StringSectionImpl<Elf64_Shdr>::fromSection(Sections[Sections[Sec->getLink()]->getLink()]);
          Sym = SymbolSectionImpl<Elf64_Shdr, Elf64_Sym>::fromSection(Sections[Sec->getLink()], Str);
          Reloc = RelocationSectionImpl<Elf64_Shdr>::fromSection(Sec, Sym, true);
        } else {
          Str = StringSectionImpl<Elf32_Shdr>::fromSection(Sections[Sections[Sec->getLink()]->getLink()]);
          Sym = SymbolSectionImpl<Elf32_Shdr, Elf32_Sym>::fromSection(Sections[Sec->getLink()], Str);
          Reloc = RelocationSectionImpl<Elf32_Shdr>::fromSection(Sec, Sym, true);
        }
        if (Reloc)
          RelocSections.push_back(Reloc);
      }
    }

    DynamicSec->setName(StrSection->getString(DynamicSec->getNameStringOffset()));
    StrSection->setName(StrSection->getString(StrSection->getNameStringOffset()));
  }

  return sectionNumber;
}

// return needed libraries
const std::vector<std::string> ELFFile::getNeededLibraries() const {
  std::shared_ptr<StringSection> StrSec;

  try {
    if (FileHeader->is64Bit()) {
      StrSec =
          std::make_shared<StringSectionImpl<Elf64_Shdr> >(*dynamic_cast<SectionImpl<
              Elf64_Shdr> *>(sections().at(DynamicSec->getLink()).get()));
    } else {
      StrSec =
          std::make_shared<StringSectionImpl<Elf32_Shdr> >(*dynamic_cast<SectionImpl<
              Elf32_Shdr> *>(sections().at(DynamicSec->getLink()).get()));
    }
  } catch (const std::out_of_range&) {
    return {};
  }
  if (!StrSec) return {};

  std::vector<std::string> result;
  for (const auto& entry : DynamicSec->getAllEntries()) {
    if (entry.tag == DT_NEEDED) {
      result.push_back(StrSec->getString(static_cast<Elf64_Word>(entry.value)));
    }
  }
  return result;
}

} // end of namespace libelfpp<commit_msg>Fix missing creation of symbol sections in 32 Bit ELF files.<commit_after>/*
 * MIT License
 *
 * Copyright (c) 2017 Kevin Kirchner
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * \file        libelfpp.cpp
 * \brief       Main source file for \p libelfpp
 * \author      Kevin Kirchner
 * \date        2017
 * \copyright   MIT LICENSE
 *
 * This source file is the main source file for \p libelfpp and implements the
 * library's public interface.
 */

#include "libelfpp/libelfpp.h"
#include "private_impl.h"
#include <cstring>
#include <iostream>

namespace libelfpp {

// Implementation of constructor
ELFFile::ELFFile(const std::string& filename) : Filename(filename) {
  std::ifstream Input(filename);
  if (!Input.good()) {
    throw std::runtime_error("File does not exist!");
  }

  unsigned char e_ident[EI_NIDENT];
  Input.seekg(0);
  Input.read(reinterpret_cast<char*>(&e_ident), sizeof(e_ident));

  // check if file is ELF file
  if (Input.gcount() != sizeof(e_ident) ||
      std::memcmp(e_ident, ELFMAG, std::strlen(ELFMAG)) != 0) {
    throw std::runtime_error("Invalid magic number!");
  }

  switch (e_ident[EI_CLASS]) {
  case ELFCLASS32:
    Is64Bit = false;
    break;
  case ELFCLASS64:
    Is64Bit = true;
    break;
  default:
    throw std::runtime_error("Invalid ELF file class!");
  }

  switch (e_ident[EI_DATA]) {
  case ELFDATA2LSB:
    IsLittleEndian = true;
    break;
  case ELFDATA2MSB:
    IsLittleEndian = false;
    break;
  default:
    throw std::runtime_error("Invalid ELF encoding!");
  }

  Converter = std::make_shared<EndianessConverter>(IsLittleEndian);

  if (Is64Bit) {
    FileHeader = std::make_shared<ELFHeaderImpl<Elf64_Ehdr>>(Converter, IsLittleEndian, Input);
  } else {
    FileHeader = std::make_shared<ELFHeaderImpl<Elf32_Ehdr>>(Converter, IsLittleEndian, Input);
  }

  loadSegmentsFromFile(Input);
  loadSectionsFromFile(Input);
  Input.close();
}

// Loads all segmetns from the file stream
Elf64_Half ELFFile::loadSegmentsFromFile(std::ifstream& stream) {
  Elf64_Half entrySize = FileHeader->getProgramHeaderSize();
  Elf64_Half segmentNumber = FileHeader->getProgramHeaderNumber();
  Elf64_Off offset = FileHeader->getProgramHeaderOffset();

  for (Elf64_Half iter = 0; iter < segmentNumber; ++iter) {
    std::shared_ptr<Segment> Seg;
    Elf64_Off baseOff, endOff, vBaseAddr, vEndAddr;

    if (Is64Bit) {
      Seg = std::make_shared<SegmentImpl<Elf64_Phdr>>(Converter);
    } else {
      Seg = std::make_shared<SegmentImpl<Elf32_Phdr>>(Converter);
    }
    Seg->loadSegment(stream, (std::streamoff) offset + iter * entrySize);
    Seg->setIndex(iter);
    Segments.push_back(Seg);

    // add associated sections
    baseOff = Seg->getOffset();
    endOff = baseOff + Seg->getFileSize();
    vBaseAddr = Seg->getVirtualAddress();
    vEndAddr = vBaseAddr + Seg->getMemorySize();

    for (const auto& Section : Sections) {
      if (Section->getFlags() & SHF_ALLOC) {
        if (vBaseAddr <= Section->getAddress() &&
            Section->getAddress() + Section->getSize() <= vEndAddr) {
          Seg->addSectionIndex(Section->getIndex());
        }
      } else {
        if (baseOff <= Section->getOffset() &&
            Section->getOffset() + Section->getSize() <= endOff) {
          Seg->addSectionIndex(Section->getIndex());
        }
      }
    }
  }

  return segmentNumber;
}

// Loads all sections from the file stream
Elf64_Half ELFFile::loadSectionsFromFile(std::ifstream& stream) {
  Elf64_Half entrySize = FileHeader->getSectionHeaderSize();
  Elf64_Half sectionNumber = FileHeader->getSectionHeaderNumber();
  Elf64_Off offset = FileHeader->getSectionHeaderOffset();

  for (Elf64_Half iter = 0; iter < sectionNumber; ++iter) {
    std::shared_ptr<Section> Sec;
    if (Is64Bit) {
      Sec = std::make_shared<SectionImpl<Elf64_Shdr>>(Converter);
    } else {
      Sec = std::make_shared<SectionImpl<Elf32_Shdr>>(Converter);
    }
    Sec->loadSection(stream, (std::streamoff) offset + iter * entrySize);
    Sec->setIndex(iter);
    Sections.push_back(Sec);

    if (Sec->getType() == SHT_DYNAMIC) {
      if (FileHeader->is64Bit()) {
        DynamicSec = DynamicSectionImpl<Elf64_Shdr, Elf64_Dyn>::fromSection(Sec);
      } else {
        DynamicSec = DynamicSectionImpl<Elf32_Shdr, Elf32_Dyn>::fromSection(Sec);
      }
    }
  }

  // get primary string section
  Elf64_Half StringIndex = FileHeader->getSectionHeaderStringTableIndex();
  if (StringIndex != SHN_UNDEF) {
    if (FileHeader->is64Bit()) {
      StrSection = StringSectionImpl<Elf64_Shdr>::fromSection(Sections[StringIndex]);
    } else {
      StrSection = StringSectionImpl<Elf32_Shdr>::fromSection(Sections[StringIndex]);
    }

    for (const auto& Sec : Sections) {
      Sec->setName(StrSection->getString(Sec->getNameStringOffset()));

      // get symbol sections in this loop, so we do not need to loop again
      if (Sec->getType() == SHT_DYNSYM || Sec->getType() == SHT_SYMTAB) {
        std::shared_ptr<SymbolSection> Sym;
        std::shared_ptr<StringSection> Str;

        if (FileHeader->is64Bit()) {
          Str = StringSectionImpl<Elf64_Shdr>::fromSection(Sections[Sec->getLink()]);
          Sym = SymbolSectionImpl<Elf64_Shdr, Elf64_Sym>::fromSection(Sec, Str);
        } else {
          Str = StringSectionImpl<Elf32_Shdr>::fromSection(Sections[Sec->getLink()]);
          Sym = SymbolSectionImpl<Elf32_Shdr, Elf32_Sym>::fromSection(Sec, Str);
        }
        if (Sym)
          SymbolSections.push_back(Sym);
      }

      if (Sec->getType() == SHT_REL || Sec->getType() == SHT_RELA) {
        std::shared_ptr<RelocationSection> Reloc;
        std::shared_ptr<StringSection> Str;
        std::shared_ptr<SymbolSection> Sym;

        if (FileHeader->is64Bit()) {
          Str = StringSectionImpl<Elf64_Shdr>::fromSection(Sections[Sections[Sec->getLink()]->getLink()]);
          Sym = SymbolSectionImpl<Elf64_Shdr, Elf64_Sym>::fromSection(Sections[Sec->getLink()], Str);
          Reloc = RelocationSectionImpl<Elf64_Shdr>::fromSection(Sec, Sym, true);
        } else {
          Str = StringSectionImpl<Elf32_Shdr>::fromSection(Sections[Sections[Sec->getLink()]->getLink()]);
          Sym = SymbolSectionImpl<Elf32_Shdr, Elf32_Sym>::fromSection(Sections[Sec->getLink()], Str);
          Reloc = RelocationSectionImpl<Elf32_Shdr>::fromSection(Sec, Sym, false);
        }
        if (Reloc)
          RelocSections.push_back(Reloc);
      }
    }

    DynamicSec->setName(StrSection->getString(DynamicSec->getNameStringOffset()));
    StrSection->setName(StrSection->getString(StrSection->getNameStringOffset()));
  }

  return sectionNumber;
}

// return needed libraries
const std::vector<std::string> ELFFile::getNeededLibraries() const {
  std::shared_ptr<StringSection> StrSec;

  try {
    if (FileHeader->is64Bit()) {
      StrSec =
          std::make_shared<StringSectionImpl<Elf64_Shdr> >(*dynamic_cast<SectionImpl<
              Elf64_Shdr> *>(sections().at(DynamicSec->getLink()).get()));
    } else {
      StrSec =
          std::make_shared<StringSectionImpl<Elf32_Shdr> >(*dynamic_cast<SectionImpl<
              Elf32_Shdr> *>(sections().at(DynamicSec->getLink()).get()));
    }
  } catch (const std::out_of_range&) {
    return {};
  }
  if (!StrSec) return {};

  std::vector<std::string> result;
  for (const auto& entry : DynamicSec->getAllEntries()) {
    if (entry.tag == DT_NEEDED) {
      result.push_back(StrSec->getString(static_cast<Elf64_Word>(entry.value)));
    }
  }
  return result;
}

} // end of namespace libelfpp<|endoftext|>


<commit_before>#include "../headers/geom.h"
#include "../headers/util.h"
#include "stdio.h"

namespace geos {

const double maximumPreciseValue=9007199254740992.0;

//double PrecisionModel::makePrecise(double val){
//	//return rint(val);
//	return ((val >= 0.0) ? floor(val+0.5) : - floor(-val+0.5));
//    /*
//     * Other options:
//     * - Math.floor(a + 0.5d);
//     * - Math.floor(a);
//     * -  (val >= 0.0) ? Math.floor(val) : - Math.floor(-val);
//     */
//}

/**
* Rounds an numeric value to the PrecisionModel grid.
*/
double PrecisionModel::makePrecise(double val) {
	double v=val*scale;
	if (val>=0.0)
		v=floor(v+0.5);
	else
		v=-floor(-v+0.5);
	return v/scale;
}

/**
* Rounds a Coordinate to the PrecisionModel grid.
*/
void PrecisionModel::makePrecise(Coordinate *coord) {
	if (modelType==FLOATING) return;
	coord->x=makePrecise(coord->x);
	coord->y=makePrecise(coord->y);
}

PrecisionModel::PrecisionModel(){
	modelType=FLOATING;
	scale=0.0;
	offsetX=0.0;
	offsetY=0.0;
}

/**
*  Creates a PrecisionModel that specifies Fixed precision.
*  Fixed-precision coordinates are represented as precise internal coordinates,
*  which are rounded to the grid defined by the scale factor.
*
*@param  scale    amount by which to multiply a coordinate after subtracting
*      the offset, to obtain a precise coordinate
*@param  offsetX  not used.
*@param  offsetY  not used.
*
* @deprecated
*/
PrecisionModel::PrecisionModel(double newScale, double newOffsetX, double newOffsetY) {
	modelType = FIXED;
	setScale(newScale);
	offsetX = newOffsetX;
	offsetY = newOffsetY;
}

/**
*  Creates a PrecisionModel that specifies Fixed precision.
*  Fixed-precision coordinates are represented as precise internal coordinates,
*  which are rounded to the grid defined by the scale factor.
*
*@param  scale    amount by which to multiply a coordinate after subtracting
*      the offset, to obtain a precise coordinate
*/
PrecisionModel::PrecisionModel(double newScale) {
	modelType=FIXED;
	setScale(scale);
	offsetX=0;
	offsetY=0;
}

PrecisionModel::PrecisionModel(const PrecisionModel &pm) {
	modelType = pm.modelType;
	scale = pm.scale;
	offsetX = pm.offsetX;
	offsetY = pm.offsetY;
}

bool PrecisionModel::isFloating(){
	return modelType == FLOATING;
}

/**
*  Returns the multiplying factor used to obtain a precise coordinate.
* This method is private because PrecisionModel is intended to
* be an immutable (value) type.
*
*@return    the amount by which to multiply a coordinate after subtracting
*      the offset
*/
double PrecisionModel::getScale(){
	return scale;
}

/**
*  Sets the multiplying factor used to obtain a precise coordinate.
* This method is private because PrecisionModel is intended to
* be an immutable (value) type.
*
*/
void PrecisionModel::setScale(double newScale) {
	scale=fabs(newScale);
}

double PrecisionModel::getOffsetX(){
	return offsetX;
}

double PrecisionModel::getOffsetY() {
	return offsetY;
}

void PrecisionModel::toInternal (Coordinate& external, Coordinate* internal) {
	if (isFloating()) {
		internal->x = external.x;
		internal->y = external.y;
	} else {
		internal->x=makePrecise(external.x);
		internal->y=makePrecise(external.y);
	}
	internal->z = external.z;
}

Coordinate* PrecisionModel::toInternal(Coordinate& external) {
	Coordinate* internal=new Coordinate();
	toInternal(external, internal);
	return internal;
}

Coordinate* PrecisionModel::toExternal(Coordinate& internal) {
	Coordinate* external=new Coordinate();
	toExternal(internal, external);
	return external;
}

void PrecisionModel::toExternal(Coordinate& internal, Coordinate* external) {
	external->x = internal.x;
	external->y = internal.y;
}

string PrecisionModel::toString() {
	string result("");
	char buffer[255];
    if (isFloating()) {
		result="Floating";
	}
    else {
		sprintf(buffer,"Fixed (Scale=%g, Offset X=%g, Offset Y=%g)",scale,offsetX,offsetY);
		result.append(buffer);
		result.append("");
    }
	return result;
}

PrecisionModel::~PrecisionModel(){}

bool operator==(PrecisionModel a, PrecisionModel b) {
	return a.isFloating() == b.isFloating() &&
			a.getOffsetX() == b.getOffsetX() &&
			a.getOffsetY() == b.getOffsetY() &&
			a.getScale() == b.getScale();
}

/**
*  Compares this {@link PrecisionModel} object with the specified object for order.
* A PrecisionModel is greater than another if it provides greater precision.
*
*@param  o  the PrecisionModel with which this PrecisionModel
*      is being compared
*@return    a negative integer, zero, or a positive integer as this PrecisionModel
*      is less than, equal to, or greater than the specified PrecisionModel
*/
int PrecisionModel::compareTo(void* o) {
	PrecisionModel *other=(PrecisionModel*) o;
	if (modelType==FLOATING && other->modelType==FLOATING) return 0;
	if (modelType==FLOATING && other->modelType!=FLOATING) return 1;
	if (modelType!=FLOATING && other->modelType==FLOATING) return -1;
	if (modelType==FIXED && other->modelType==FIXED) {
		if (scale>other->scale)
			return 1;
		else if (scale<other->scale)
			return -1;
		else
			return 0;
	}
	Assert::shouldNeverReachHere("Unknown Precision Model type encountered");
	return 0;
}
}

<commit_msg>Throw an exception if scale is 0. Added Log entry.<commit_after>/*
* $Log$
* Revision 1.13  2003/10/09 10:10:05  strk
* Throw an exception if scale is 0. Added Log entry.
*
*/
#include "../headers/geom.h"
#include "../headers/util.h"
#include "stdio.h"

namespace geos {

const double maximumPreciseValue=9007199254740992.0;

//double PrecisionModel::makePrecise(double val){
//	//return rint(val);
//	return ((val >= 0.0) ? floor(val+0.5) : - floor(-val+0.5));
//    /*
//     * Other options:
//     * - Math.floor(a + 0.5d);
//     * - Math.floor(a);
//     * -  (val >= 0.0) ? Math.floor(val) : - Math.floor(-val);
//     */
//}

/**
* Rounds an numeric value to the PrecisionModel grid.
*/
double PrecisionModel::makePrecise(double val) {
	double v=val*scale;
	if (val>=0.0)
		v=floor(v+0.5);
	else
		v=-floor(-v+0.5);
	return v/scale;
}

/**
* Rounds a Coordinate to the PrecisionModel grid.
*/
void PrecisionModel::makePrecise(Coordinate *coord) {
	if (modelType==FLOATING) return;
	coord->x=makePrecise(coord->x);
	coord->y=makePrecise(coord->y);
}

PrecisionModel::PrecisionModel(){
	modelType=FLOATING;
	scale=0.0;
	offsetX=0.0;
	offsetY=0.0;
}

/**
*  Creates a PrecisionModel that specifies Fixed precision.
*  Fixed-precision coordinates are represented as precise internal coordinates,
*  which are rounded to the grid defined by the scale factor.
*
*@param  scale    amount by which to multiply a coordinate after subtracting
*      the offset, to obtain a precise coordinate
*@param  offsetX  not used.
*@param  offsetY  not used.
*
* @deprecated
*/
PrecisionModel::PrecisionModel(double newScale, double newOffsetX, double newOffsetY) {
	if ( newScale == 0 ) throw new IllegalArgumentException("PrecisionModel scale cannot be 0");
	modelType = FIXED;
	setScale(newScale);
	offsetX = newOffsetX;
	offsetY = newOffsetY;
}

/**
*  Creates a PrecisionModel that specifies Fixed precision.
*  Fixed-precision coordinates are represented as precise internal coordinates,
*  which are rounded to the grid defined by the scale factor.
*
*@param  scale    amount by which to multiply a coordinate after subtracting
*      the offset, to obtain a precise coordinate
*/
PrecisionModel::PrecisionModel(double newScale) {
	modelType=FIXED;
	setScale(scale);
	offsetX=0;
	offsetY=0;
}

PrecisionModel::PrecisionModel(const PrecisionModel &pm) {
	modelType = pm.modelType;
	scale = pm.scale;
	offsetX = pm.offsetX;
	offsetY = pm.offsetY;
}

bool PrecisionModel::isFloating(){
	return modelType == FLOATING;
}

/**
*  Returns the multiplying factor used to obtain a precise coordinate.
* This method is private because PrecisionModel is intended to
* be an immutable (value) type.
*
*@return    the amount by which to multiply a coordinate after subtracting
*      the offset
*/
double PrecisionModel::getScale(){
	return scale;
}

/**
*  Sets the multiplying factor used to obtain a precise coordinate.
* This method is private because PrecisionModel is intended to
* be an immutable (value) type.
*
*/
void PrecisionModel::setScale(double newScale) {
	scale=fabs(newScale);
}

double PrecisionModel::getOffsetX(){
	return offsetX;
}

double PrecisionModel::getOffsetY() {
	return offsetY;
}

void PrecisionModel::toInternal (Coordinate& external, Coordinate* internal) {
	if (isFloating()) {
		internal->x = external.x;
		internal->y = external.y;
	} else {
		internal->x=makePrecise(external.x);
		internal->y=makePrecise(external.y);
	}
	internal->z = external.z;
}

Coordinate* PrecisionModel::toInternal(Coordinate& external) {
	Coordinate* internal=new Coordinate();
	toInternal(external, internal);
	return internal;
}

Coordinate* PrecisionModel::toExternal(Coordinate& internal) {
	Coordinate* external=new Coordinate();
	toExternal(internal, external);
	return external;
}

void PrecisionModel::toExternal(Coordinate& internal, Coordinate* external) {
	external->x = internal.x;
	external->y = internal.y;
}

string PrecisionModel::toString() {
	string result("");
	char buffer[255];
    if (isFloating()) {
		result="Floating";
	}
    else {
		sprintf(buffer,"Fixed (Scale=%g, Offset X=%g, Offset Y=%g)",scale,offsetX,offsetY);
		result.append(buffer);
		result.append("");
    }
	return result;
}

PrecisionModel::~PrecisionModel(){}

bool operator==(PrecisionModel a, PrecisionModel b) {
	return a.isFloating() == b.isFloating() &&
			a.getOffsetX() == b.getOffsetX() &&
			a.getOffsetY() == b.getOffsetY() &&
			a.getScale() == b.getScale();
}

/**
*  Compares this {@link PrecisionModel} object with the specified object for order.
* A PrecisionModel is greater than another if it provides greater precision.
*
*@param  o  the PrecisionModel with which this PrecisionModel
*      is being compared
*@return    a negative integer, zero, or a positive integer as this PrecisionModel
*      is less than, equal to, or greater than the specified PrecisionModel
*/
int PrecisionModel::compareTo(void* o) {
	PrecisionModel *other=(PrecisionModel*) o;
	if (modelType==FLOATING && other->modelType==FLOATING) return 0;
	if (modelType==FLOATING && other->modelType!=FLOATING) return 1;
	if (modelType!=FLOATING && other->modelType==FLOATING) return -1;
	if (modelType==FIXED && other->modelType==FIXED) {
		if (scale>other->scale)
			return 1;
		else if (scale<other->scale)
			return -1;
		else
			return 0;
	}
	Assert::shouldNeverReachHere("Unknown Precision Model type encountered");
	return 0;
}
}

<|endoftext|>


<commit_before>/**
 * Copyright (C) 2011 Trever Fischer <tdfischer@fedoraproject.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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 Lesser GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include "logmodel.h"
#include "refreshjob.h"

#include "DataModel/subject.h"

#include <QtGui/QFileIconProvider>
#include <QtCore/QDebug>
#include <QtCore/QUrl>
#include <QtCore/QDir>
#include <QtCore/QCryptographicHash>

namespace QZeitgeist
{

LogModel::LogModel(QObject *parent)
    : QAbstractItemModel(parent)
    , m_monitor(0)
    , m_iconMode(URIIcons)
{
    m_log = new QZeitgeist::Log(this);
    m_storageState = QZeitgeist::Log::Any;
    m_range = QZeitgeist::DataModel::TimeRange::always();
    m_eventTemplates << QZeitgeist::DataModel::Event();
    m_type = QZeitgeist::Log::MostRecentSubjects;
    m_pool = new QThreadPool(this);
}

LogModel::~LogModel()
{
}

void LogModel::setIconMode(IconMode mode)
{
    m_iconMode = mode;
    emit dataChanged(index(0), index(rowCount()));
}

void LogModel::diffEvents(const QZeitgeist::DataModel::EventList &events)
{
    //TODO: Implement dyanmic programming for a proper diff algorithm.
    //This probably depends on the datamodel objects not being QObjects.
    QZeitgeist::DataModel::EventList newEvents = events;
    QZeitgeist::DataModel::EventList::iterator currentIt = m_events.begin();
    QZeitgeist::DataModel::EventList::iterator newIt = newEvents.begin();
    int currentRow = 0;
    while(currentIt != m_events.end() && newIt != newEvents.end()) {
        if (newIt->id() == currentIt->id()) {
            newIt++;
            currentIt++;
            currentRow++;
        } else if (newIt->timestamp() >= currentIt->timestamp()) {
            beginInsertRows(QModelIndex(), currentRow, currentRow);
            currentIt = m_events.insert(currentIt, *newIt);
            endInsertRows();
            newIt = newEvents.erase(newIt);
            currentIt++;
            currentRow++;
        } else if (newIt->timestamp() < currentIt->timestamp()) {
            beginRemoveRows(QModelIndex(), currentRow, currentRow);
            currentIt = m_events.erase(currentIt);
            endRemoveRows();
        }
    }
    if (newIt != newEvents.end()) {
        beginInsertRows(QModelIndex(), currentRow, currentRow+newEvents.size()-1);
        while(newIt != newEvents.end()) {
            currentIt = m_events.insert(currentIt, *newIt);
            currentRow++;
            currentIt++;
            newIt++;
        }
        endInsertRows();
    }
    if (currentIt != m_events.end()) {
        beginRemoveRows(QModelIndex(), currentRow, m_events.size()-1);
        while(currentIt != m_events.end()) {
            currentIt = m_events.erase(currentIt);
        }
        endRemoveRows();
    }
}

void LogModel::refresh()
{
    RefreshJob *refreshJob = new RefreshJob(m_range,
                                            m_eventTemplates,
                                            m_storageState,
                                            10000,
                                            m_type,
                                            m_log,
                                            this);
    connect(refreshJob, SIGNAL(done(QZeitgeist::DataModel::EventList)), this, SLOT(refreshDone(QZeitgeist::DataModel::EventList)));
    m_pool->start(refreshJob);
    if (m_monitor)
        m_log->removeMonitor(m_monitor);
    m_monitor = m_log->installMonitor(m_range, m_eventTemplates);
    connect(m_monitor, SIGNAL(eventsInserted(QZeitgeist::DataModel::TimeRange,QZeitgeist::DataModel::EventList)), this, SLOT(eventsInserted(QZeitgeist::DataModel::TimeRange,QZeitgeist::DataModel::EventList)));
    connect(m_monitor, SIGNAL(eventsDeleted(QZeitgeist::DataModel::TimeRange,QZeitgeist::DataModel::EventIdList&)), this, SLOT(eventsDeleted(QZeitgeist::DataModel::TimeRange,QZeitgeist::DataModel::EventIdList)));
}

void LogModel::eventsInserted(const QZeitgeist::DataModel::TimeRange &range, const QZeitgeist::DataModel::EventList &events)
{
    QZeitgeist::DataModel::EventList oldEvents = m_events;
    foreach(const QZeitgeist::DataModel::Event &evt, events) {
        oldEvents << evt;
    }
    diffEvents(oldEvents);
}

void LogModel::eventsDeleted(const QZeitgeist::DataModel::TimeRange &range, const QZeitgeist::DataModel::EventIdList &events)
{
    QZeitgeist::DataModel::EventList oldEvents = m_events;
    foreach(int id, events) {
        foreach(const QZeitgeist::DataModel::Event &evt, oldEvents) {
            if (evt.id() == id)
                oldEvents.removeOne(evt);
        }
    }
    diffEvents(oldEvents);
}

void LogModel::refreshDone(const QZeitgeist::DataModel::EventList &results)
{
    diffEvents(results);
}

int LogModel::rowCount(const QModelIndex &idx) const
{
    if (idx.isValid())
        return 0;
    return m_events.size();
}

int LogModel::columnCount(const QModelIndex &idx) const
{
    if (idx.isValid())
        return 0;
    return 1;
}

QModelIndex LogModel::parent(const QModelIndex &idx) const
{
    Q_UNUSED(idx);
    return QModelIndex();
}

QVariant LogModel::data(const QModelIndex &idx, int role) const
{
    if (idx.isValid() && idx.row() >= 0 && idx.row() < rowCount() && idx.column() == 0) {
        QZeitgeist::DataModel::Event event = m_events[idx.row()];
        switch(role) {
            case Qt::DisplayRole:
                return event.subjects()[0].text();
            case Qt::DecorationRole:
                return iconForEvent(event);
            case EventRole:
                return QVariant::fromValue<QZeitgeist::DataModel::Event>(event);
            case TimeRole:
                return event.timestamp();
            case IDRole:
                return event.id();
            case URLRole:
                return event.subjects()[0].uri();
            case MimeRole:
                return event.subjects()[0].mimeType();
            case ActorRole:
                return event.actor();
            case ThumbnailRole:
                return thumbnailForEvent(event);
            default:
                return QVariant();
        }
    }
    return QVariant();
}

QPixmap LogModel::thumbnailForEvent(const QZeitgeist::DataModel::Event &event) const
{
    //FIXME: Implement caching
    QString url(event.subjects()[0].uri());
    QDir thumbDir(QString("%1/.thumbnails/large/").arg(QDir::homePath()));
    QString snapshotName = QString("%1.png").arg(QString(QCryptographicHash::hash(url.toUtf8(), QCryptographicHash::Md5).toHex()));
    if (thumbDir.exists(snapshotName)) {
        return QPixmap(thumbDir.absoluteFilePath(snapshotName), "JPEG");
    }
    return QPixmap();
}

QIcon LogModel::iconForActor(const QString &actor) const
{
    QString desktopFile = QUrl(actor).authority().section('.', 0, 0);
    return QIcon::fromTheme(desktopFile);
}

QIcon LogModel::iconForEvent(const QZeitgeist::DataModel::Event &event) const
{
    QFileIconProvider icons;
    QIcon ret = iconForActor(event.actor());
    if (m_iconMode == ActorIcons)
        return ret;
    foreach(QZeitgeist::DataModel::Subject subject, event.subjects()) {
        QUrl url = subject.uri();
        if (url.scheme() == "file") {
            QFileInfo info(url.path());
            ret = icons.icon(info);
            if (!ret.isNull())
              break;
        }
    }
    if (ret.isNull())
        ret = iconForActor(event.actor());
}

QModelIndex LogModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!parent.isValid() && row >= 0 && row < rowCount() && column == 0)
        return createIndex(row, column);
    return QModelIndex();
}

void LogModel::setRange(const QZeitgeist::DataModel::TimeRange &range)
{
    m_range = range;
    refresh();
}

Qt::ItemFlags LogModel::flags(const QModelIndex &index) const
{
    if (index.isValid() && index.row() >= 0 && index.row() < rowCount() && index.column() == 0)
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    return 0;
}

QStringList LogModel::eventIconOverlays(const QZeitgeist::DataModel::Event &event) const
{
    QStringList overlays;
    QZeitgeist::DataModel::Subject subject = event.subjects()[0];
    /*switch(subject.interpretation()) {
        case QZeitgeist::Interpretation::Subject::NFOAudio:
            overlays << "applications-m
    }*/
    QString mime = subject.mimeType();
    overlays << mime.replace('/', '-');
    return overlays;
}

QZeitgeist::DataModel::TimeRange LogModel::range() const
{
    return m_range;
}

void LogModel::setResultType(QZeitgeist::Log::ResultType type)
{
    m_type = type;
    refresh();
}

QZeitgeist::Log::ResultType LogModel::resultType() const
{
    return m_type;
}

void LogModel::setEventTemplates(const QZeitgeist::DataModel::EventList &templates)
{
    m_eventTemplates = templates;
    refresh();
}

DataModel::EventList LogModel::eventTemplates() const
{
    return m_eventTemplates;
}

} // namespace QZeitgeist

#include "logmodel.moc"
<commit_msg>build++<commit_after>/**
 * Copyright (C) 2011 Trever Fischer <tdfischer@fedoraproject.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser 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 Lesser GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include "logmodel.h"
#include "refreshjob.h"

#include "DataModel/subject.h"

#include <QtGui/QFileIconProvider>
#include <QtCore/QDebug>
#include <QtCore/QUrl>
#include <QtCore/QDir>
#include <QtCore/QCryptographicHash>

namespace QZeitgeist
{

LogModel::LogModel(QObject *parent)
    : QAbstractItemModel(parent)
    , m_monitor(0)
    , m_iconMode(URIIcons)
{
    m_log = new QZeitgeist::Log(this);
    m_storageState = QZeitgeist::Log::Any;
    m_range = QZeitgeist::DataModel::TimeRange::always();
    m_eventTemplates << QZeitgeist::DataModel::Event();
    m_type = QZeitgeist::Log::MostRecentSubjects;
    m_pool = new QThreadPool(this);
}

LogModel::~LogModel()
{
}

void LogModel::setIconMode(IconMode mode)
{
    m_iconMode = mode;
    emit dataChanged(index(0, 0), index(rowCount(), 0));
}

void LogModel::diffEvents(const QZeitgeist::DataModel::EventList &events)
{
    //TODO: Implement dyanmic programming for a proper diff algorithm.
    //This probably depends on the datamodel objects not being QObjects.
    QZeitgeist::DataModel::EventList newEvents = events;
    QZeitgeist::DataModel::EventList::iterator currentIt = m_events.begin();
    QZeitgeist::DataModel::EventList::iterator newIt = newEvents.begin();
    int currentRow = 0;
    while(currentIt != m_events.end() && newIt != newEvents.end()) {
        if (newIt->id() == currentIt->id()) {
            newIt++;
            currentIt++;
            currentRow++;
        } else if (newIt->timestamp() >= currentIt->timestamp()) {
            beginInsertRows(QModelIndex(), currentRow, currentRow);
            currentIt = m_events.insert(currentIt, *newIt);
            endInsertRows();
            newIt = newEvents.erase(newIt);
            currentIt++;
            currentRow++;
        } else if (newIt->timestamp() < currentIt->timestamp()) {
            beginRemoveRows(QModelIndex(), currentRow, currentRow);
            currentIt = m_events.erase(currentIt);
            endRemoveRows();
        }
    }
    if (newIt != newEvents.end()) {
        beginInsertRows(QModelIndex(), currentRow, currentRow+newEvents.size()-1);
        while(newIt != newEvents.end()) {
            currentIt = m_events.insert(currentIt, *newIt);
            currentRow++;
            currentIt++;
            newIt++;
        }
        endInsertRows();
    }
    if (currentIt != m_events.end()) {
        beginRemoveRows(QModelIndex(), currentRow, m_events.size()-1);
        while(currentIt != m_events.end()) {
            currentIt = m_events.erase(currentIt);
        }
        endRemoveRows();
    }
}

void LogModel::refresh()
{
    RefreshJob *refreshJob = new RefreshJob(m_range,
                                            m_eventTemplates,
                                            m_storageState,
                                            10000,
                                            m_type,
                                            m_log,
                                            this);
    connect(refreshJob, SIGNAL(done(QZeitgeist::DataModel::EventList)), this, SLOT(refreshDone(QZeitgeist::DataModel::EventList)));
    m_pool->start(refreshJob);
    if (m_monitor)
        m_log->removeMonitor(m_monitor);
    m_monitor = m_log->installMonitor(m_range, m_eventTemplates);
    connect(m_monitor, SIGNAL(eventsInserted(QZeitgeist::DataModel::TimeRange,QZeitgeist::DataModel::EventList)), this, SLOT(eventsInserted(QZeitgeist::DataModel::TimeRange,QZeitgeist::DataModel::EventList)));
    connect(m_monitor, SIGNAL(eventsDeleted(QZeitgeist::DataModel::TimeRange,QZeitgeist::DataModel::EventIdList&)), this, SLOT(eventsDeleted(QZeitgeist::DataModel::TimeRange,QZeitgeist::DataModel::EventIdList)));
}

void LogModel::eventsInserted(const QZeitgeist::DataModel::TimeRange &range, const QZeitgeist::DataModel::EventList &events)
{
    QZeitgeist::DataModel::EventList oldEvents = m_events;
    foreach(const QZeitgeist::DataModel::Event &evt, events) {
        oldEvents << evt;
    }
    diffEvents(oldEvents);
}

void LogModel::eventsDeleted(const QZeitgeist::DataModel::TimeRange &range, const QZeitgeist::DataModel::EventIdList &events)
{
    QZeitgeist::DataModel::EventList oldEvents = m_events;
    foreach(int id, events) {
        foreach(const QZeitgeist::DataModel::Event &evt, oldEvents) {
            if (evt.id() == id)
                oldEvents.removeOne(evt);
        }
    }
    diffEvents(oldEvents);
}

void LogModel::refreshDone(const QZeitgeist::DataModel::EventList &results)
{
    diffEvents(results);
}

int LogModel::rowCount(const QModelIndex &idx) const
{
    if (idx.isValid())
        return 0;
    return m_events.size();
}

int LogModel::columnCount(const QModelIndex &idx) const
{
    if (idx.isValid())
        return 0;
    return 1;
}

QModelIndex LogModel::parent(const QModelIndex &idx) const
{
    Q_UNUSED(idx);
    return QModelIndex();
}

QVariant LogModel::data(const QModelIndex &idx, int role) const
{
    if (idx.isValid() && idx.row() >= 0 && idx.row() < rowCount() && idx.column() == 0) {
        QZeitgeist::DataModel::Event event = m_events[idx.row()];
        switch(role) {
            case Qt::DisplayRole:
                return event.subjects()[0].text();
            case Qt::DecorationRole:
                return iconForEvent(event);
            case EventRole:
                return QVariant::fromValue<QZeitgeist::DataModel::Event>(event);
            case TimeRole:
                return event.timestamp();
            case IDRole:
                return event.id();
            case URLRole:
                return event.subjects()[0].uri();
            case MimeRole:
                return event.subjects()[0].mimeType();
            case ActorRole:
                return event.actor();
            case ThumbnailRole:
                return thumbnailForEvent(event);
            default:
                return QVariant();
        }
    }
    return QVariant();
}

QPixmap LogModel::thumbnailForEvent(const QZeitgeist::DataModel::Event &event) const
{
    //FIXME: Implement caching
    QString url(event.subjects()[0].uri());
    QDir thumbDir(QString("%1/.thumbnails/large/").arg(QDir::homePath()));
    QString snapshotName = QString("%1.png").arg(QString(QCryptographicHash::hash(url.toUtf8(), QCryptographicHash::Md5).toHex()));
    if (thumbDir.exists(snapshotName)) {
        return QPixmap(thumbDir.absoluteFilePath(snapshotName), "JPEG");
    }
    return QPixmap();
}

QIcon LogModel::iconForActor(const QString &actor) const
{
    QString desktopFile = QUrl(actor).authority().section('.', 0, 0);
    return QIcon::fromTheme(desktopFile);
}

QIcon LogModel::iconForEvent(const QZeitgeist::DataModel::Event &event) const
{
    QFileIconProvider icons;
    QIcon ret = iconForActor(event.actor());
    if (m_iconMode == ActorIcons)
        return ret;
    foreach(QZeitgeist::DataModel::Subject subject, event.subjects()) {
        QUrl url = subject.uri();
        if (url.scheme() == "file") {
            QFileInfo info(url.path());
            ret = icons.icon(info);
            if (!ret.isNull())
              break;
        }
    }
    if (ret.isNull())
        ret = iconForActor(event.actor());
}

QModelIndex LogModel::index(int row, int column, const QModelIndex &parent) const
{
    if (!parent.isValid() && row >= 0 && row < rowCount() && column == 0)
        return createIndex(row, column);
    return QModelIndex();
}

void LogModel::setRange(const QZeitgeist::DataModel::TimeRange &range)
{
    m_range = range;
    refresh();
}

Qt::ItemFlags LogModel::flags(const QModelIndex &index) const
{
    if (index.isValid() && index.row() >= 0 && index.row() < rowCount() && index.column() == 0)
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    return 0;
}

QStringList LogModel::eventIconOverlays(const QZeitgeist::DataModel::Event &event) const
{
    QStringList overlays;
    QZeitgeist::DataModel::Subject subject = event.subjects()[0];
    /*switch(subject.interpretation()) {
        case QZeitgeist::Interpretation::Subject::NFOAudio:
            overlays << "applications-m
    }*/
    QString mime = subject.mimeType();
    overlays << mime.replace('/', '-');
    return overlays;
}

QZeitgeist::DataModel::TimeRange LogModel::range() const
{
    return m_range;
}

void LogModel::setResultType(QZeitgeist::Log::ResultType type)
{
    m_type = type;
    refresh();
}

QZeitgeist::Log::ResultType LogModel::resultType() const
{
    return m_type;
}

void LogModel::setEventTemplates(const QZeitgeist::DataModel::EventList &templates)
{
    m_eventTemplates = templates;
    refresh();
}

DataModel::EventList LogModel::eventTemplates() const
{
    return m_eventTemplates;
}

} // namespace QZeitgeist

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