<commit_before>//===- MemoryBufferCacheTest.cpp - MemoryBufferCache tests ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/MemoryBufferCache.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace clang;

namespace {

std::unique_ptr<MemoryBuffer> getBuffer(int I) {
  SmallVector<char, 8> Bytes;
  raw_svector_ostream(Bytes) << "data:" << I;
  return MemoryBuffer::getMemBuffer(StringRef(Bytes.data(), Bytes.size()), "",
                                    /* RequiresNullTerminator = */ false);
}

TEST(MemoryBufferCacheTest, addBuffer) {
  auto B1 = getBuffer(1);
  auto B2 = getBuffer(2);
  auto B3 = getBuffer(3);
  auto *RawB1 = B1.get();
  auto *RawB2 = B2.get();
  auto *RawB3 = B3.get();

  // Add a few buffers.
  MemoryBufferCache Cache;
  EXPECT_EQ(RawB1, &Cache.addBuffer("1", std::move(B1)));
  EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2)));
  EXPECT_EQ(RawB3, &Cache.addBuffer("3", std::move(B3)));
  EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
  EXPECT_EQ(RawB2, Cache.lookupBuffer("2"));
  EXPECT_EQ(RawB3, Cache.lookupBuffer("3"));
  EXPECT_FALSE(Cache.isBufferFinal("1"));
  EXPECT_FALSE(Cache.isBufferFinal("2"));
  EXPECT_FALSE(Cache.isBufferFinal("3"));

  // Remove the middle buffer.
  EXPECT_FALSE(Cache.tryToRemoveBuffer("2"));
  EXPECT_EQ(nullptr, Cache.lookupBuffer("2"));
  EXPECT_FALSE(Cache.isBufferFinal("2"));

  // Replace the middle buffer.
  B2 = getBuffer(2);
  ASSERT_NE(RawB2, B2.get());
  RawB2 = B2.get();
  EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2)));

  // Check that nothing is final.
  EXPECT_FALSE(Cache.isBufferFinal("1"));
  EXPECT_FALSE(Cache.isBufferFinal("2"));
  EXPECT_FALSE(Cache.isBufferFinal("3"));
}

TEST(MemoryBufferCacheTest, finalizeCurrentBuffers) {
  // Add a buffer.
  MemoryBufferCache Cache;
  auto B1 = getBuffer(1);
  auto *RawB1 = B1.get();
  Cache.addBuffer("1", std::move(B1));
  ASSERT_FALSE(Cache.isBufferFinal("1"));

  // Finalize it.
  Cache.finalizeCurrentBuffers();
  EXPECT_TRUE(Cache.isBufferFinal("1"));
  EXPECT_TRUE(Cache.tryToRemoveBuffer("1"));
  EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
  EXPECT_TRUE(Cache.isBufferFinal("1"));

  // Repeat.
  auto B2 = getBuffer(2);
  auto *RawB2 = B2.get();
  Cache.addBuffer("2", std::move(B2));
  EXPECT_FALSE(Cache.isBufferFinal("2"));

  Cache.finalizeCurrentBuffers();
  EXPECT_TRUE(Cache.isBufferFinal("1"));
  EXPECT_TRUE(Cache.isBufferFinal("2"));
  EXPECT_TRUE(Cache.tryToRemoveBuffer("1"));
  EXPECT_TRUE(Cache.tryToRemoveBuffer("2"));
  EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
  EXPECT_EQ(RawB2, Cache.lookupBuffer("2"));
  EXPECT_TRUE(Cache.isBufferFinal("1"));
  EXPECT_TRUE(Cache.isBufferFinal("2"));
}

} // namespace
<commit_msg>Modules: Remove an invalid check in unit tests for r298278<commit_after>//===- MemoryBufferCacheTest.cpp - MemoryBufferCache tests ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "clang/Basic/MemoryBufferCache.h"
#include "llvm/Support/MemoryBuffer.h"
#include "gtest/gtest.h"

using namespace llvm;
using namespace clang;

namespace {

std::unique_ptr<MemoryBuffer> getBuffer(int I) {
  SmallVector<char, 8> Bytes;
  raw_svector_ostream(Bytes) << "data:" << I;
  return MemoryBuffer::getMemBuffer(StringRef(Bytes.data(), Bytes.size()), "",
                                    /* RequiresNullTerminator = */ false);
}

TEST(MemoryBufferCacheTest, addBuffer) {
  auto B1 = getBuffer(1);
  auto B2 = getBuffer(2);
  auto B3 = getBuffer(3);
  auto *RawB1 = B1.get();
  auto *RawB2 = B2.get();
  auto *RawB3 = B3.get();

  // Add a few buffers.
  MemoryBufferCache Cache;
  EXPECT_EQ(RawB1, &Cache.addBuffer("1", std::move(B1)));
  EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2)));
  EXPECT_EQ(RawB3, &Cache.addBuffer("3", std::move(B3)));
  EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
  EXPECT_EQ(RawB2, Cache.lookupBuffer("2"));
  EXPECT_EQ(RawB3, Cache.lookupBuffer("3"));
  EXPECT_FALSE(Cache.isBufferFinal("1"));
  EXPECT_FALSE(Cache.isBufferFinal("2"));
  EXPECT_FALSE(Cache.isBufferFinal("3"));

  // Remove the middle buffer.
  EXPECT_FALSE(Cache.tryToRemoveBuffer("2"));
  EXPECT_EQ(nullptr, Cache.lookupBuffer("2"));
  EXPECT_FALSE(Cache.isBufferFinal("2"));

  // Replace the middle buffer.
  B2 = getBuffer(2);
  RawB2 = B2.get();
  EXPECT_EQ(RawB2, &Cache.addBuffer("2", std::move(B2)));

  // Check that nothing is final.
  EXPECT_FALSE(Cache.isBufferFinal("1"));
  EXPECT_FALSE(Cache.isBufferFinal("2"));
  EXPECT_FALSE(Cache.isBufferFinal("3"));
}

TEST(MemoryBufferCacheTest, finalizeCurrentBuffers) {
  // Add a buffer.
  MemoryBufferCache Cache;
  auto B1 = getBuffer(1);
  auto *RawB1 = B1.get();
  Cache.addBuffer("1", std::move(B1));
  ASSERT_FALSE(Cache.isBufferFinal("1"));

  // Finalize it.
  Cache.finalizeCurrentBuffers();
  EXPECT_TRUE(Cache.isBufferFinal("1"));
  EXPECT_TRUE(Cache.tryToRemoveBuffer("1"));
  EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
  EXPECT_TRUE(Cache.isBufferFinal("1"));

  // Repeat.
  auto B2 = getBuffer(2);
  auto *RawB2 = B2.get();
  Cache.addBuffer("2", std::move(B2));
  EXPECT_FALSE(Cache.isBufferFinal("2"));

  Cache.finalizeCurrentBuffers();
  EXPECT_TRUE(Cache.isBufferFinal("1"));
  EXPECT_TRUE(Cache.isBufferFinal("2"));
  EXPECT_TRUE(Cache.tryToRemoveBuffer("1"));
  EXPECT_TRUE(Cache.tryToRemoveBuffer("2"));
  EXPECT_EQ(RawB1, Cache.lookupBuffer("1"));
  EXPECT_EQ(RawB2, Cache.lookupBuffer("2"));
  EXPECT_TRUE(Cache.isBufferFinal("1"));
  EXPECT_TRUE(Cache.isBufferFinal("2"));
}

} // namespace
<|endoftext|>


<commit_before>// Author: Binghong Chen
// Date: 2016.06.30

#include <petuum_ps_common/include/petuum_ps.hpp>
#include <petuum_ps_common/include/system_gflags.hpp>
//#include <petuum_ps_common/include/configs.hpp>
//#include <petuum_ps_common/util/utils.hpp>
#include <thread>
#include <map>
#include <vector>
#include <cstdint>
#include <glog/logging.h>
#include <gflags/gflags.h>

namespace petuum {

enum RowType {
  kUndefinedRow = 0
  , kDenseFloatRow = 1
  , kDenseIntRow = 2
  , kSparseFloatRow = 3
  , kSparseIntRow = 4
};

struct TableConfig {
  // Required config for table.
  std::string name;   // name is used to fetch the table
  RowType row_type{kUndefinedRow};
  int64_t num_cols{-1};
  int64_t num_rows{-1};
  int staleness{0};

  // Optional configs
  // Number of rows to cache in process cache. Default -1 means all rows.
  int64_t num_rows_to_cache{-1};
  // Estimated upper bound # of pending oplogs in terms of # of rows. Default
  // -1 means all rows.
  int64_t num_oplog_rows{-1};
  // kDenseRowOpLog or kSparseRowOpLog
  int oplog_type{RowOpLogType::kDenseRowOpLog};
};

class PsApp {
public:
  void Run(int num_worker_threads=1) {
    process_barrier_.reset(new boost::barrier(num_worker_threads));

    // Step 1.0. Register common row types
    PSTableGroup::RegisterRow<
      DenseRow<float>>(kDenseFloatRow);
    PSTableGroup::RegisterRow<
      DenseRow<int32_t>>(kDenseIntRow);
    PSTableGroup::RegisterRow<
      SparseRow<float>>(kSparseFloatRow);
    PSTableGroup::RegisterRow<
      SparseRow<int>>(kSparseIntRow);

    std::vector<TableConfig> configs = ConfigTables();

    // Step 1.1. Initialize Table Group
    TableGroupConfig table_group_config;
    table_group_config.num_comm_channels_per_client = 1;
    table_group_config.num_total_clients = FLAGS_num_clients;
    table_group_config.num_tables = configs.size();
    GetHostInfos(FLAGS_hostfile, &table_group_config.host_map);
    table_group_config.client_id = FLAGS_client_id;
    // +1 to include the main() thread
    table_group_config.num_local_app_threads = num_worker_threads + 1;
    // Consistency model
    table_group_config.consistency_model = SSPPush;
    // False to disallow table access for the main thread.
    PSTableGroup::Init(table_group_config, false);

    client_id_ = FLAGS_client_id;

    // Create Tables
    for (int i = 0; i < configs.size(); ++i) {
      auto config = ConvertTableConfig(configs[i]);
      PSTableGroup::CreateTable(i, config);
      table_names_[configs[i].name] = i;
    }
    PSTableGroup::CreateTableDone();

    InitApp();

    // Spin num_worker_threads to run.
    LOG(INFO) << "Starting program with " << num_worker_threads << " threads "
      << "on client " << table_group_config.client_id;
    std::vector<std::thread> threads(num_worker_threads);
    for (auto& thr : threads) {
      thr = std::thread(&PsApp::RunWorkerThread, this);
    }
    for (auto& thr : threads) {
      thr.join();
    }

    // Shutdown PSTableGroup
    PSTableGroup::ShutDown();
    LOG(INFO) << "Program finished and shut down!";
  }

protected:
  PsApp() : thread_counter_(0) {};

  ~PsApp() {};

  // InitApp() can data loading in single-thread. Or it can do nothing. It may
  // not access PS table.
  virtual void InitApp() = 0;

  // Return a set of table configuration. See TableConfig struct.
  virtual std::vector<TableConfig> ConfigTables() = 0;

  virtual void WorkerThread(int client_id, int thread_id) = 0;

  template<typename V>
  Table<V> GetTable(const std::string& table_name) {
    auto it = table_names_.find(table_name);
    CHECK(it != table_names_.cend()) << "Table " << table_name
      << " was not registered";
    return PSTableGroup::GetTableOrDie<float>(it->second);
  }

private:
  void RunWorkerThread() {
    PSTableGroup::RegisterThread();
    int thread_id = thread_counter_++;
    WorkerThread(client_id_, thread_id);
    PSTableGroup::DeregisterThread();
  }

  // Convert from a simplified TableConfig to ClientTableConfig
  ClientTableConfig ConvertTableConfig(const TableConfig& config) {
    // Check required fields in TableConfig
    CHECK_NE("", config.name) << "Table name must be set";
    CHECK_NE(-1, config.num_rows)
      << "Table " << config.name << " num_rows must be set.";
    CHECK_NE(-1, config.num_cols)
      << "Table " << config.name << " num_cols must be set.";
    CHECK_NE(kUndefinedRow, config.row_type)
      << "Table " << config.name << " row_type must be set.";

    ClientTableConfig table_config;
    table_config.table_info.table_staleness = config.staleness;
    table_config.table_info.row_type = config.row_type;
    table_config.table_info.row_capacity = config.num_cols;

    table_config.process_cache_capacity = config.num_rows_to_cache == -1 ?
      config.num_rows : config.num_rows_to_cache;
    table_config.table_info.row_oplog_type = config.oplog_type;
    table_config.oplog_capacity = config.num_oplog_rows == -1 ?
      config.num_rows : config.num_oplog_rows;
    table_config.table_info.dense_row_oplog_capacity =
      table_config.table_info.row_capacity;
    return table_config;
  }

protected:
  boost::scoped_ptr<boost::barrier> process_barrier_;

private:
  std::atomic<int> thread_counter_;
  int client_id_;

  // Map table name to PS's internal table ID.
  std::map<std::string, int> table_names_;
};
}  // namespace petuum
<commit_msg>Update ps_app.hpp<commit_after>// Author: Binghong Chen
// Date: 2016.06.30

#include <petuum_ps_common/include/petuum_ps.hpp>
#include <petuum_ps_common/include/system_gflags.hpp>
//#include <petuum_ps_common/include/configs.hpp>
//#include <petuum_ps_common/util/utils.hpp>
#include <thread>
#include <map>
#include <vector>
#include <cstdint>
#include <glog/logging.h>
#include <gflags/gflags.h>

namespace petuum {

enum RowType {
  kUndefinedRow = 0
  , kDenseFloatRow = 1
  , kDenseIntRow = 2
  , kSparseFloatRow = 3
  , kSparseIntRow = 4
};

struct TableConfig {
  // Required config for table.
  std::string name;   // name is used to fetch the table
  RowType row_type{kUndefinedRow};
  int64_t num_cols{-1};
  int64_t num_rows{-1};
  int staleness{0};

  // Optional configs
  // Number of rows to cache in process cache. Default -1 means all rows.
  int64_t num_rows_to_cache{-1};
  // Estimated upper bound # of pending oplogs in terms of # of rows. Default
  // -1 means all rows.
  int64_t num_oplog_rows{-1};
  // kDenseRowOpLog or kSparseRowOpLog
  int oplog_type{RowOpLogType::kDenseRowOpLog};
};

class PsApp {
public:
  void Run(int num_worker_threads=1) {
    process_barrier_.reset(new boost::barrier(num_worker_threads));

    // Step 1.0. Register common row types
    PSTableGroup::RegisterRow<
      DenseRow<float>>(kDenseFloatRow);
    PSTableGroup::RegisterRow<
      DenseRow<int32_t>>(kDenseIntRow);
    PSTableGroup::RegisterRow<
      SparseRow<float>>(kSparseFloatRow);
    PSTableGroup::RegisterRow<
      SparseRow<int>>(kSparseIntRow);

    std::vector<TableConfig> configs = ConfigTables();

    // Step 1.1. Initialize Table Group
    TableGroupConfig table_group_config;
    table_group_config.num_comm_channels_per_client = 1;
    table_group_config.num_total_clients = FLAGS_num_clients;
    table_group_config.num_tables = configs.size();
    GetHostInfos(FLAGS_hostfile, &table_group_config.host_map);
    table_group_config.client_id = FLAGS_client_id;
    // +1 to include the main() thread
    table_group_config.num_local_app_threads = num_worker_threads + 1;
    // Consistency model
    table_group_config.consistency_model = SSPPush;
    // False to disallow table access for the main thread.
    PSTableGroup::Init(table_group_config, false);

    client_id_ = FLAGS_client_id;

    // Create Tables
    for (int i = 0; i < configs.size(); ++i) {
      auto config = ConvertTableConfig(configs[i]);
      PSTableGroup::CreateTable(i, config);
      table_names_[configs[i].name] = i;
    }
    PSTableGroup::CreateTableDone();

    InitApp();

    // Spin num_worker_threads to run.
    LOG(INFO) << "Starting program with " << num_worker_threads << " threads "
      << "on client " << table_group_config.client_id;
    std::vector<std::thread> threads(num_worker_threads);
    for (auto& thr : threads) {
      thr = std::thread(&PsApp::RunWorkerThread, this);
    }
    for (auto& thr : threads) {
      thr.join();
    }

    // Shutdown PSTableGroup
    PSTableGroup::ShutDown();
    LOG(INFO) << "Program finished and shut down!";
  }

protected:
  PsApp() : thread_counter_(0) {};

  ~PsApp() {};

  // InitApp() can data loading in single-thread. Or it can do nothing. It may
  // not access PS table.
  virtual void InitApp() = 0;

  // Return a set of table configuration. See TableConfig struct.
  virtual std::vector<TableConfig> ConfigTables() = 0;

  virtual void WorkerThread(int client_id, int thread_id) = 0;

  template<typename V>
  Table<V> GetTable(const std::string& table_name) {
    auto it = table_names_.find(table_name);
    CHECK(it != table_names_.cend()) << "Table " << table_name
      << " was not registered";
    return PSTableGroup::GetTableOrDie<V>(it->second);
  }

private:
  void RunWorkerThread() {
    PSTableGroup::RegisterThread();
    int thread_id = thread_counter_++;
    WorkerThread(client_id_, thread_id);
    PSTableGroup::DeregisterThread();
  }

  // Convert from a simplified TableConfig to ClientTableConfig
  ClientTableConfig ConvertTableConfig(const TableConfig& config) {
    // Check required fields in TableConfig
    CHECK_NE("", config.name) << "Table name must be set";
    CHECK_NE(-1, config.num_rows)
      << "Table " << config.name << " num_rows must be set.";
    CHECK_NE(-1, config.num_cols)
      << "Table " << config.name << " num_cols must be set.";
    CHECK_NE(kUndefinedRow, config.row_type)
      << "Table " << config.name << " row_type must be set.";

    ClientTableConfig table_config;
    table_config.table_info.table_staleness = config.staleness;
    table_config.table_info.row_type = config.row_type;
    table_config.table_info.row_capacity = config.num_cols;

    table_config.process_cache_capacity = config.num_rows_to_cache == -1 ?
      config.num_rows : config.num_rows_to_cache;
    table_config.table_info.row_oplog_type = config.oplog_type;
    table_config.oplog_capacity = config.num_oplog_rows == -1 ?
      config.num_rows : config.num_oplog_rows;
    table_config.table_info.dense_row_oplog_capacity =
      table_config.table_info.row_capacity;
    return table_config;
  }

protected:
  boost::scoped_ptr<boost::barrier> process_barrier_;

private:
  std::atomic<int> thread_counter_;
  int client_id_;

  // Map table name to PS's internal table ID.
  std::map<std::string, int> table_names_;
};
}  // namespace petuum
<|endoftext|>


<commit_before>/* Please refer to license.txt */

#pragma once

#include <iostream>

namespace GEngine
{

namespace mdata
{

//Argh, I really need to program a doubly linked list, linked list, and binary tree here.
//Or find a good library supplying these.

//Really, just a wrapper to x, y, z, so that I only have to manage one variable instead of three.
class Location3D
{
public:
	long x, y, z;

	Location3D()
	{
		x = 0;
		y = 0;
		z = 0;
	}

	//Sets all three variables at once.
	void set(long X, long Y, long Z)
	{
		x = X;
		y = Y;
		z = Z;
	}
};

template <typename T>
class DoublyLinkedList
{
private:
	DoublyLinkedList *next_neighbor, *previous_neighbor;
	T *the_data;
	bool delete_data;

public:
	DoublyLinkedList()
	{
		next_neighbor = nullptr;
		previous_neighbor = nullptr;

		delete_data = true;

		the_data = nullptr;
	}

	DoublyLinkedList(T &_data, bool copy = false)
	{
		next_neighbor = nullptr;
		previous_neighbor = nullptr;

		if (copy)
		{
			the_data = new T;
			*the_data = _data;
			delete_data = true;
		}
		else
		{
			the_data = &_data;
			delete_data = false;
		}
	}

	~DoublyLinkedList()
	{
		if (delete_data && the_data)
		{
			delete the_data;
		}
		the_data = nullptr;

		if (next_neighbor && previous_neighbor)
		{
			//Has a left and right neighbor. Splice this guy out.
			next_neighbor->previous_neighbor = previous_neighbor;
			previous_neighbor->next_neighbor = next_neighbor;
			next_neighbor = nullptr;
			previous_neighbor = nullptr;
		}
		else if (next_neighbor)
		{
			//It's the start of the line. Make the next one the start of the line.
			next_neighbor->previous_neighbor = nullptr;
			next_neighbor = nullptr;
		}
		else if (previous_neighbor)
		{
			//It's the end of the line. Make the previos one the end of the line.
			previous_neighbor->next_neighbor = nullptr;
			previous_neighbor = nullptr;
		}
	}

	void alloc(T &_data, bool copy)
	{
		if (the_data && delete_data)
		{
			delete the_data;
		}

		if (copy)
		{
			the_data = new T;
			*the_data = _data;
			delete_data = true;
		}
		else
		{
			the_data = &_data;
			delete_data = false;
		}
	}

	void allocNext()
	{
		if (next_neighbor) //Make sure it doesn't already exist.
		{
			//Does. That's bad.
			std::cout << "*** mdata::DoublyLinkedList *** ERROR IN FUNCTION allocNext(): DoublyLinkedList already already has next_neighbor on line" << __LINE__ << " in file \"" << __FILE__ <<  "\"\n";
			throw; //TODO: It's error time again -- they got you runnin' through the night! It's a terrifying time~
		}

		next_neighbor = new DoublyLinkedList();
		next_neighbor->previous_neighbor = this;
	}

	void allocNext(T &_data, bool copy = false)
	{
		if (next_neighbor) //Make sure it doesn't already exist.
		{
			//Does. That's bad.
			std::cout << "*** mdata::DoublyLinkedList *** ERROR IN FUNCTION allocNext(): DoublyLinkedList already already has next_neighbor on line" << __LINE__ << " in file \"" << __FILE__ <<  "\"\n";
			throw; //TODO: It's error time again -- they got you runnin' through the night! It's a terrifying time~
		}
		next_neighbor = new DoublyLinkedList(_data, copy);
		next_neighbor->previous_neighbor = this;
	}

	void allocPrevious()
	{
		if (previous_neighbor) //Make sure it doesn't already exist.
		{
			//Does. That's bad.
			std::cout << "*** mdata::DoublyLinkedList *** ERROR IN FUNCTION allocPrevious(): DoublyLinkedList already already has previous_neighbor on line" << __LINE__ << " in file \"" << __FILE__ <<  "\"\n";
			throw; //TODO: It's error time again -- they got you runnin' through the night! It's a terrifying time~
		}
		previous_neighbor = new DoublyLinkedList();
		previous_neighbor->next_neighbor = this;
	}

	void allocPrevious(T &_data, bool copy = false)
	{
		if (previous_neighbor) //Make sure it doesn't already exist.
		{
			//Does. That's bad.
			std::cout << "*** mdata::DoublyLinkedList *** ERROR IN FUNCTION allocPrevious(): DoublyLinkedList already already has previous_neighbor on line" << __LINE__ << " in file \"" << __FILE__ <<  "\"\n";
			throw; //TODO: It's error time again -- they got you runnin' through the night! It's a terrifying time~
		}
		previous_neighbor = new DoublyLinkedList(_data, copy);
		previous_neighbor->next_neighbor = this;
	}

	DoublyLinkedList* next()
	{
		return next_neighbor;
	}

	DoublyLinkedList* previous()
	{
		return previous_neighbor;
	}

	T* data()
	{
		return the_data;
	}
};

/*
 * Right, so this is pretty simple.
 * Basically, it checks for t in vector.
 * It returns an iterator pointing to that part of the vector if it found it, nullptr otherwise.
 */
template<typename T>
typename std::vector<T>::iterator* inVector(std::vector<T> &vector, T &t)
{
	typename std::vector<T>::iterator iter = vector.begin();

	for (; iter != vector.end(); ++iter)
	{
		if ((*iter) == t)
		{
			return iter; //Found it!
		}
	}

	return nullptr; //Didn't find it.
}

} //namespace mdata

} //namespace GEngine
<commit_msg>Forgot to include vector in data.hpp so that there's no issues with the inVector function.<commit_after>/* Please refer to license.txt */

#pragma once

#include <iostream>
#include <vector>

namespace GEngine
{

namespace mdata
{

//Argh, I really need to program a doubly linked list, linked list, and binary tree here.
//Or find a good library supplying these.

//Really, just a wrapper to x, y, z, so that I only have to manage one variable instead of three.
class Location3D
{
public:
	long x, y, z;

	Location3D()
	{
		x = 0;
		y = 0;
		z = 0;
	}

	//Sets all three variables at once.
	void set(long X, long Y, long Z)
	{
		x = X;
		y = Y;
		z = Z;
	}
};

template <typename T>
class DoublyLinkedList
{
private:
	DoublyLinkedList *next_neighbor, *previous_neighbor;
	T *the_data;
	bool delete_data;

public:
	DoublyLinkedList()
	{
		next_neighbor = nullptr;
		previous_neighbor = nullptr;

		delete_data = true;

		the_data = nullptr;
	}

	DoublyLinkedList(T &_data, bool copy = false)
	{
		next_neighbor = nullptr;
		previous_neighbor = nullptr;

		if (copy)
		{
			the_data = new T;
			*the_data = _data;
			delete_data = true;
		}
		else
		{
			the_data = &_data;
			delete_data = false;
		}
	}

	~DoublyLinkedList()
	{
		if (delete_data && the_data)
		{
			delete the_data;
		}
		the_data = nullptr;

		if (next_neighbor && previous_neighbor)
		{
			//Has a left and right neighbor. Splice this guy out.
			next_neighbor->previous_neighbor = previous_neighbor;
			previous_neighbor->next_neighbor = next_neighbor;
			next_neighbor = nullptr;
			previous_neighbor = nullptr;
		}
		else if (next_neighbor)
		{
			//It's the start of the line. Make the next one the start of the line.
			next_neighbor->previous_neighbor = nullptr;
			next_neighbor = nullptr;
		}
		else if (previous_neighbor)
		{
			//It's the end of the line. Make the previos one the end of the line.
			previous_neighbor->next_neighbor = nullptr;
			previous_neighbor = nullptr;
		}
	}

	void alloc(T &_data, bool copy)
	{
		if (the_data && delete_data)
		{
			delete the_data;
		}

		if (copy)
		{
			the_data = new T;
			*the_data = _data;
			delete_data = true;
		}
		else
		{
			the_data = &_data;
			delete_data = false;
		}
	}

	void allocNext()
	{
		if (next_neighbor) //Make sure it doesn't already exist.
		{
			//Does. That's bad.
			std::cout << "*** mdata::DoublyLinkedList *** ERROR IN FUNCTION allocNext(): DoublyLinkedList already already has next_neighbor on line" << __LINE__ << " in file \"" << __FILE__ <<  "\"\n";
			throw; //TODO: It's error time again -- they got you runnin' through the night! It's a terrifying time~
		}

		next_neighbor = new DoublyLinkedList();
		next_neighbor->previous_neighbor = this;
	}

	void allocNext(T &_data, bool copy = false)
	{
		if (next_neighbor) //Make sure it doesn't already exist.
		{
			//Does. That's bad.
			std::cout << "*** mdata::DoublyLinkedList *** ERROR IN FUNCTION allocNext(): DoublyLinkedList already already has next_neighbor on line" << __LINE__ << " in file \"" << __FILE__ <<  "\"\n";
			throw; //TODO: It's error time again -- they got you runnin' through the night! It's a terrifying time~
		}
		next_neighbor = new DoublyLinkedList(_data, copy);
		next_neighbor->previous_neighbor = this;
	}

	void allocPrevious()
	{
		if (previous_neighbor) //Make sure it doesn't already exist.
		{
			//Does. That's bad.
			std::cout << "*** mdata::DoublyLinkedList *** ERROR IN FUNCTION allocPrevious(): DoublyLinkedList already already has previous_neighbor on line" << __LINE__ << " in file \"" << __FILE__ <<  "\"\n";
			throw; //TODO: It's error time again -- they got you runnin' through the night! It's a terrifying time~
		}
		previous_neighbor = new DoublyLinkedList();
		previous_neighbor->next_neighbor = this;
	}

	void allocPrevious(T &_data, bool copy = false)
	{
		if (previous_neighbor) //Make sure it doesn't already exist.
		{
			//Does. That's bad.
			std::cout << "*** mdata::DoublyLinkedList *** ERROR IN FUNCTION allocPrevious(): DoublyLinkedList already already has previous_neighbor on line" << __LINE__ << " in file \"" << __FILE__ <<  "\"\n";
			throw; //TODO: It's error time again -- they got you runnin' through the night! It's a terrifying time~
		}
		previous_neighbor = new DoublyLinkedList(_data, copy);
		previous_neighbor->next_neighbor = this;
	}

	DoublyLinkedList* next()
	{
		return next_neighbor;
	}

	DoublyLinkedList* previous()
	{
		return previous_neighbor;
	}

	T* data()
	{
		return the_data;
	}
};

/*
 * Right, so this is pretty simple.
 * Basically, it checks for t in vector.
 * It returns an iterator pointing to that part of the vector if it found it, nullptr otherwise.
 */
template<typename T>
typename std::vector<T>::iterator* inVector(std::vector<T> &vector, T &t)
{
	typename std::vector<T>::iterator iter = vector.begin();

	for (; iter != vector.end(); ++iter)
	{
		if ((*iter) == t)
		{
			return iter; //Found it!
		}
	}

	return nullptr; //Didn't find it.
}

} //namespace mdata

} //namespace GEngine
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "cpptoolsplugin.h"
#include "completionsettingspage.h"
#include "cppfilesettingspage.h"
#include "cppcodestylesettingspage.h"
#include "cppclassesfilter.h"
#include "cppfunctionsfilter.h"
#include "cppcurrentdocumentfilter.h"
#include "cppmodelmanager.h"
#include "cpptoolsconstants.h"
#include "cpplocatorfilter.h"
#include "symbolsfindfilter.h"
#include "cpptoolssettings.h"

#include <extensionsystem/pluginmanager.h>

#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/id.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/vcsmanager.h>
#include <coreplugin/documentmanager.h>
#include <cppeditor/cppeditorconstants.h>

#include <QtConcurrentRun>
#include <QFutureSynchronizer>
#include <utils/runextensions.h>

#include <find/ifindfilter.h>
#include <find/searchresultwindow.h>
#include <utils/filesearch.h>
#include <utils/qtcassert.h>

#include <QtPlugin>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#include <QSettings>
#include <QMenu>
#include <QAction>

#include <sstream>

using namespace CppTools::Internal;
using namespace CPlusPlus;

enum { debug = 0 };

static CppToolsPlugin *m_instance = 0;

CppToolsPlugin::CppToolsPlugin() :
    m_modelManager(0),
    m_fileSettings(new CppFileSettings)
{
    m_instance = this;
}

CppToolsPlugin::~CppToolsPlugin()
{
    m_instance = 0;
    m_modelManager = 0; // deleted automatically
}

bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
{
    Q_UNUSED(arguments)
    Q_UNUSED(error)

    m_settings = new CppToolsSettings(this); // force registration of cpp tools settings

    // Objects
    m_modelManager = new CppModelManager(this);
    Core::VcsManager *vcsManager = Core::ICore::vcsManager();
    connect(vcsManager, SIGNAL(repositoryChanged(QString)),
            m_modelManager, SLOT(updateModifiedSourceFiles()));
    connect(Core::DocumentManager::instance(), SIGNAL(filesChangedInternally(QStringList)),
            m_modelManager, SLOT(updateSourceFiles(QStringList)));
    addAutoReleasedObject(m_modelManager);

    addAutoReleasedObject(new CppLocatorFilter(m_modelManager));
    addAutoReleasedObject(new CppClassesFilter(m_modelManager));
    addAutoReleasedObject(new CppFunctionsFilter(m_modelManager));
    addAutoReleasedObject(new CppCurrentDocumentFilter(m_modelManager, Core::ICore::editorManager()));
    addAutoReleasedObject(new CppFileSettingsPage(m_fileSettings));
    addAutoReleasedObject(new SymbolsFindFilter(m_modelManager));
    addAutoReleasedObject(new CppCodeStyleSettingsPage);

    // Menus
    Core::ActionContainer *mtools = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
    Core::ActionContainer *mcpptools = Core::ActionManager::createMenu(CppTools::Constants::M_TOOLS_CPP);
    QMenu *menu = mcpptools->menu();
    menu->setTitle(tr("&C++"));
    menu->setEnabled(true);
    mtools->addMenu(mcpptools);

    // Actions
    Core::Context context(CppEditor::Constants::C_CPPEDITOR);

    QAction *switchAction = new QAction(tr("Switch Header/Source"), this);
    Core::Command *command = Core::ActionManager::registerAction(switchAction, Constants::SWITCH_HEADER_SOURCE, context, true);
    command->setDefaultKeySequence(QKeySequence(Qt::Key_F4));
    mcpptools->addAction(command);
    connect(switchAction, SIGNAL(triggered()), this, SLOT(switchHeaderSource()));

    return true;
}

void CppToolsPlugin::extensionsInitialized()
{
    // The Cpp editor plugin, which is loaded later on, registers the Cpp mime types,
    // so, apply settings here
    m_fileSettings->fromSettings(Core::ICore::settings());
    if (!m_fileSettings->applySuffixesToMimeDB())
        qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n");
}

ExtensionSystem::IPlugin::ShutdownFlag CppToolsPlugin::aboutToShutdown()
{
    return SynchronousShutdown;
}

void CppToolsPlugin::switchHeaderSource()
{
    Core::IEditor *editor = Core::EditorManager::currentEditor();
    QString otherFile = correspondingHeaderOrSource(editor->document()->fileName());
    if (!otherFile.isEmpty())
        Core::EditorManager::openEditor(otherFile);
}

static QStringList findFilesInProject(const QString &name,
                                   const ProjectExplorer::Project *project)
{
    if (debug)
        qDebug() << Q_FUNC_INFO << name << project;

    if (!project)
        return QStringList();

    QString pattern = QString(1, QLatin1Char('/'));
    pattern += name;
    const QStringList projectFiles = project->files(ProjectExplorer::Project::AllFiles);
    const QStringList::const_iterator pcend = projectFiles.constEnd();
    QStringList candidateList;
    for (QStringList::const_iterator it = projectFiles.constBegin(); it != pcend; ++it) {
        if (it->endsWith(pattern))
            candidateList.append(*it);
    }
    return candidateList;
}

// Figure out file type
enum FileType {
    HeaderFile,
    C_SourceFile,
    CPP_SourceFile,
    ObjectiveCPP_SourceFile,
    UnknownType
};

static inline FileType fileType(const Core::MimeDatabase *mimeDatase, const  QFileInfo & fi)
{
    const Core::MimeType mimeType = mimeDatase->findByFile(fi);
    if (!mimeType)
        return UnknownType;
    const QString typeName = mimeType.type();
    if (typeName == QLatin1String(CppTools::Constants::C_SOURCE_MIMETYPE))
        return C_SourceFile;
    if (typeName == QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE))
        return CPP_SourceFile;
    if (typeName == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE))
        return ObjectiveCPP_SourceFile;
    if (typeName == QLatin1String(CppTools::Constants::C_HEADER_MIMETYPE)
        || typeName == QLatin1String(CppTools::Constants::CPP_HEADER_MIMETYPE))
        return HeaderFile;
    return UnknownType;
}

// Return the suffixes that should be checked when trying to find a
// source belonging to a header and vice versa
static QStringList matchingCandidateSuffixes(const Core::MimeDatabase *mimeDatase, FileType type)
{
    switch (type) {
    case UnknownType:
        break;
    case HeaderFile: // Note that C/C++ headers are undistinguishable
        return mimeDatase->findByType(QLatin1String(CppTools::Constants::C_SOURCE_MIMETYPE)).suffixes()
               + mimeDatase->findByType(QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE)).suffixes()
               + mimeDatase->findByType(QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)).suffixes();
    case C_SourceFile:
        return mimeDatase->findByType(QLatin1String(CppTools::Constants::C_HEADER_MIMETYPE)).suffixes();
    case CPP_SourceFile:
    case ObjectiveCPP_SourceFile:
        return mimeDatase->findByType(QLatin1String(CppTools::Constants::CPP_HEADER_MIMETYPE)).suffixes();
    }
    return QStringList();
}

static QStringList baseNameWithAllSuffixes(const QString &baseName, const QStringList &suffixes)
{
    QStringList result;
    const QChar dot = QLatin1Char('.');
    foreach (const QString &suffix, suffixes) {
        QString fileName = baseName;
        fileName += dot;
        fileName += suffix;
        result += fileName;
    }
    return result;
}

static int commonStringLength(const QString &s1, const QString &s2)
{
    int length = qMin(s1.length(), s2.length());
    for (int i = 0; i < length; ++i)
        if (s1[i] != s2[i])
            return i;
    return length;
}

QString CppToolsPlugin::correspondingHeaderOrSourceI(const QString &fileName) const
{
    const QFileInfo fi(fileName);
    if (m_headerSourceMapping.contains(fi.absoluteFilePath()))
        return m_headerSourceMapping.value(fi.absoluteFilePath());

    const Core::MimeDatabase *mimeDatase = Core::ICore::mimeDatabase();
    ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::currentProject();

    const FileType type = fileType(mimeDatase, fi);

    if (debug)
        qDebug() << Q_FUNC_INFO << fileName <<  type;

    if (type == UnknownType)
        return QString();

    const QString baseName = fi.completeBaseName();
    const QString privateHeaderSuffix = QLatin1String("_p");
    const QStringList suffixes = matchingCandidateSuffixes(mimeDatase, type);

    QStringList candidateFileNames = baseNameWithAllSuffixes(baseName, suffixes);
    if (type == HeaderFile) {
        if (baseName.endsWith(privateHeaderSuffix)) {
            QString sourceBaseName = baseName;
            sourceBaseName.truncate(sourceBaseName.size() - privateHeaderSuffix.size());
            candidateFileNames += baseNameWithAllSuffixes(sourceBaseName, suffixes);
        }
    } else {
        QString privateHeaderBaseName = baseName;
        privateHeaderBaseName.append(privateHeaderSuffix);
        candidateFileNames += baseNameWithAllSuffixes(privateHeaderBaseName, suffixes);
    }

    const QDir absoluteDir = fi.absoluteDir();

    // Try to find a file in the same directory first
    foreach (const QString &candidateFileName, candidateFileNames) {
        const QFileInfo candidateFi(absoluteDir, candidateFileName);
        if (candidateFi.isFile()) {
            m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
            m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
            return candidateFi.absoluteFilePath();
        }
    }

    // Find files in the project
    if (project) {
        QString bestFileName;
        int compareValue = 0;
        foreach (const QString &candidateFileName, candidateFileNames) {
            const QStringList projectFiles = findFilesInProject(candidateFileName, project);
            // Find the file having the most common path with fileName
            foreach (const QString projectFile, projectFiles) {
                int value = commonStringLength(fileName, projectFile);
                if (value > compareValue) {
                    compareValue = value;
                    bestFileName = projectFile;
                }
            }
        }
        if (!bestFileName.isEmpty()) {
            const QFileInfo candidateFi(bestFileName);
            QTC_ASSERT(candidateFi.isFile(), return QString());
            m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
            m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
            return candidateFi.absoluteFilePath();
        }
    }

    return QString();
}

QString CppToolsPlugin::correspondingHeaderOrSource(const QString &fileName)
{
    const QString rc = m_instance->correspondingHeaderOrSourceI(fileName);
    if (debug)
        qDebug() << Q_FUNC_INFO << fileName << rc;
    return rc;
}

Q_EXPORT_PLUGIN(CppToolsPlugin)
<commit_msg>Don't cache mapping between source and private header<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "cpptoolsplugin.h"
#include "completionsettingspage.h"
#include "cppfilesettingspage.h"
#include "cppcodestylesettingspage.h"
#include "cppclassesfilter.h"
#include "cppfunctionsfilter.h"
#include "cppcurrentdocumentfilter.h"
#include "cppmodelmanager.h"
#include "cpptoolsconstants.h"
#include "cpplocatorfilter.h"
#include "symbolsfindfilter.h"
#include "cpptoolssettings.h"

#include <extensionsystem/pluginmanager.h>

#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/id.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/vcsmanager.h>
#include <coreplugin/documentmanager.h>
#include <cppeditor/cppeditorconstants.h>

#include <QtConcurrentRun>
#include <QFutureSynchronizer>
#include <utils/runextensions.h>

#include <find/ifindfilter.h>
#include <find/searchresultwindow.h>
#include <utils/filesearch.h>
#include <utils/qtcassert.h>

#include <QtPlugin>
#include <QFileInfo>
#include <QDir>
#include <QDebug>
#include <QSettings>
#include <QMenu>
#include <QAction>

#include <sstream>

using namespace CppTools::Internal;
using namespace CPlusPlus;

enum { debug = 0 };

static CppToolsPlugin *m_instance = 0;

CppToolsPlugin::CppToolsPlugin() :
    m_modelManager(0),
    m_fileSettings(new CppFileSettings)
{
    m_instance = this;
}

CppToolsPlugin::~CppToolsPlugin()
{
    m_instance = 0;
    m_modelManager = 0; // deleted automatically
}

bool CppToolsPlugin::initialize(const QStringList &arguments, QString *error)
{
    Q_UNUSED(arguments)
    Q_UNUSED(error)

    m_settings = new CppToolsSettings(this); // force registration of cpp tools settings

    // Objects
    m_modelManager = new CppModelManager(this);
    Core::VcsManager *vcsManager = Core::ICore::vcsManager();
    connect(vcsManager, SIGNAL(repositoryChanged(QString)),
            m_modelManager, SLOT(updateModifiedSourceFiles()));
    connect(Core::DocumentManager::instance(), SIGNAL(filesChangedInternally(QStringList)),
            m_modelManager, SLOT(updateSourceFiles(QStringList)));
    addAutoReleasedObject(m_modelManager);

    addAutoReleasedObject(new CppLocatorFilter(m_modelManager));
    addAutoReleasedObject(new CppClassesFilter(m_modelManager));
    addAutoReleasedObject(new CppFunctionsFilter(m_modelManager));
    addAutoReleasedObject(new CppCurrentDocumentFilter(m_modelManager, Core::ICore::editorManager()));
    addAutoReleasedObject(new CppFileSettingsPage(m_fileSettings));
    addAutoReleasedObject(new SymbolsFindFilter(m_modelManager));
    addAutoReleasedObject(new CppCodeStyleSettingsPage);

    // Menus
    Core::ActionContainer *mtools = Core::ActionManager::actionContainer(Core::Constants::M_TOOLS);
    Core::ActionContainer *mcpptools = Core::ActionManager::createMenu(CppTools::Constants::M_TOOLS_CPP);
    QMenu *menu = mcpptools->menu();
    menu->setTitle(tr("&C++"));
    menu->setEnabled(true);
    mtools->addMenu(mcpptools);

    // Actions
    Core::Context context(CppEditor::Constants::C_CPPEDITOR);

    QAction *switchAction = new QAction(tr("Switch Header/Source"), this);
    Core::Command *command = Core::ActionManager::registerAction(switchAction, Constants::SWITCH_HEADER_SOURCE, context, true);
    command->setDefaultKeySequence(QKeySequence(Qt::Key_F4));
    mcpptools->addAction(command);
    connect(switchAction, SIGNAL(triggered()), this, SLOT(switchHeaderSource()));

    return true;
}

void CppToolsPlugin::extensionsInitialized()
{
    // The Cpp editor plugin, which is loaded later on, registers the Cpp mime types,
    // so, apply settings here
    m_fileSettings->fromSettings(Core::ICore::settings());
    if (!m_fileSettings->applySuffixesToMimeDB())
        qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n");
}

ExtensionSystem::IPlugin::ShutdownFlag CppToolsPlugin::aboutToShutdown()
{
    return SynchronousShutdown;
}

void CppToolsPlugin::switchHeaderSource()
{
    Core::IEditor *editor = Core::EditorManager::currentEditor();
    QString otherFile = correspondingHeaderOrSource(editor->document()->fileName());
    if (!otherFile.isEmpty())
        Core::EditorManager::openEditor(otherFile);
}

static QStringList findFilesInProject(const QString &name,
                                   const ProjectExplorer::Project *project)
{
    if (debug)
        qDebug() << Q_FUNC_INFO << name << project;

    if (!project)
        return QStringList();

    QString pattern = QString(1, QLatin1Char('/'));
    pattern += name;
    const QStringList projectFiles = project->files(ProjectExplorer::Project::AllFiles);
    const QStringList::const_iterator pcend = projectFiles.constEnd();
    QStringList candidateList;
    for (QStringList::const_iterator it = projectFiles.constBegin(); it != pcend; ++it) {
        if (it->endsWith(pattern))
            candidateList.append(*it);
    }
    return candidateList;
}

// Figure out file type
enum FileType {
    HeaderFile,
    C_SourceFile,
    CPP_SourceFile,
    ObjectiveCPP_SourceFile,
    UnknownType
};

static inline FileType fileType(const Core::MimeDatabase *mimeDatase, const  QFileInfo & fi)
{
    const Core::MimeType mimeType = mimeDatase->findByFile(fi);
    if (!mimeType)
        return UnknownType;
    const QString typeName = mimeType.type();
    if (typeName == QLatin1String(CppTools::Constants::C_SOURCE_MIMETYPE))
        return C_SourceFile;
    if (typeName == QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE))
        return CPP_SourceFile;
    if (typeName == QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE))
        return ObjectiveCPP_SourceFile;
    if (typeName == QLatin1String(CppTools::Constants::C_HEADER_MIMETYPE)
        || typeName == QLatin1String(CppTools::Constants::CPP_HEADER_MIMETYPE))
        return HeaderFile;
    return UnknownType;
}

// Return the suffixes that should be checked when trying to find a
// source belonging to a header and vice versa
static QStringList matchingCandidateSuffixes(const Core::MimeDatabase *mimeDatase, FileType type)
{
    switch (type) {
    case UnknownType:
        break;
    case HeaderFile: // Note that C/C++ headers are undistinguishable
        return mimeDatase->findByType(QLatin1String(CppTools::Constants::C_SOURCE_MIMETYPE)).suffixes()
               + mimeDatase->findByType(QLatin1String(CppTools::Constants::CPP_SOURCE_MIMETYPE)).suffixes()
               + mimeDatase->findByType(QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)).suffixes();
    case C_SourceFile:
        return mimeDatase->findByType(QLatin1String(CppTools::Constants::C_HEADER_MIMETYPE)).suffixes();
    case CPP_SourceFile:
    case ObjectiveCPP_SourceFile:
        return mimeDatase->findByType(QLatin1String(CppTools::Constants::CPP_HEADER_MIMETYPE)).suffixes();
    }
    return QStringList();
}

static QStringList baseNameWithAllSuffixes(const QString &baseName, const QStringList &suffixes)
{
    QStringList result;
    const QChar dot = QLatin1Char('.');
    foreach (const QString &suffix, suffixes) {
        QString fileName = baseName;
        fileName += dot;
        fileName += suffix;
        result += fileName;
    }
    return result;
}

static int commonStringLength(const QString &s1, const QString &s2)
{
    int length = qMin(s1.length(), s2.length());
    for (int i = 0; i < length; ++i)
        if (s1[i] != s2[i])
            return i;
    return length;
}

QString CppToolsPlugin::correspondingHeaderOrSourceI(const QString &fileName) const
{
    const QFileInfo fi(fileName);
    if (m_headerSourceMapping.contains(fi.absoluteFilePath()))
        return m_headerSourceMapping.value(fi.absoluteFilePath());

    const Core::MimeDatabase *mimeDatase = Core::ICore::mimeDatabase();
    ProjectExplorer::Project *project = ProjectExplorer::ProjectExplorerPlugin::currentProject();

    const FileType type = fileType(mimeDatase, fi);

    if (debug)
        qDebug() << Q_FUNC_INFO << fileName <<  type;

    if (type == UnknownType)
        return QString();

    const QString baseName = fi.completeBaseName();
    const QString privateHeaderSuffix = QLatin1String("_p");
    const QStringList suffixes = matchingCandidateSuffixes(mimeDatase, type);

    QStringList candidateFileNames = baseNameWithAllSuffixes(baseName, suffixes);
    if (type == HeaderFile) {
        if (baseName.endsWith(privateHeaderSuffix)) {
            QString sourceBaseName = baseName;
            sourceBaseName.truncate(sourceBaseName.size() - privateHeaderSuffix.size());
            candidateFileNames += baseNameWithAllSuffixes(sourceBaseName, suffixes);
        }
    } else {
        QString privateHeaderBaseName = baseName;
        privateHeaderBaseName.append(privateHeaderSuffix);
        candidateFileNames += baseNameWithAllSuffixes(privateHeaderBaseName, suffixes);
    }

    const QDir absoluteDir = fi.absoluteDir();

    // Try to find a file in the same directory first
    foreach (const QString &candidateFileName, candidateFileNames) {
        const QFileInfo candidateFi(absoluteDir, candidateFileName);
        if (candidateFi.isFile()) {
            m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
            if (type != HeaderFile || !baseName.endsWith(privateHeaderSuffix))
                m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
            return candidateFi.absoluteFilePath();
        }
    }

    // Find files in the project
    if (project) {
        QString bestFileName;
        int compareValue = 0;
        foreach (const QString &candidateFileName, candidateFileNames) {
            const QStringList projectFiles = findFilesInProject(candidateFileName, project);
            // Find the file having the most common path with fileName
            foreach (const QString projectFile, projectFiles) {
                int value = commonStringLength(fileName, projectFile);
                if (value > compareValue) {
                    compareValue = value;
                    bestFileName = projectFile;
                }
            }
        }
        if (!bestFileName.isEmpty()) {
            const QFileInfo candidateFi(bestFileName);
            QTC_ASSERT(candidateFi.isFile(), return QString());
            m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
            m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
            return candidateFi.absoluteFilePath();
        }
    }

    return QString();
}

QString CppToolsPlugin::correspondingHeaderOrSource(const QString &fileName)
{
    const QString rc = m_instance->correspondingHeaderOrSourceI(fileName);
    if (debug)
        qDebug() << Q_FUNC_INFO << fileName << rc;
    return rc;
}

Q_EXPORT_PLUGIN(CppToolsPlugin)
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "valgrindplugin.h"

#include "callgrindsettings.h"
#include "callgrindtool.h"
#include "memchecksettings.h"
#include "memchecktool.h"
#include "valgrindsettings.h"

#include <analyzerbase/analyzerconstants.h>
#include <analyzerbase/analyzermanager.h>

#include <utils/qtcassert.h>

#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtCore/QtPlugin>
#include <QtGui/QAction>

using namespace Analyzer;

namespace Valgrind {
namespace Internal {

/////////////////////////////////////////////////////////////////////////////////
//
// ValgrindPlugin
//
/////////////////////////////////////////////////////////////////////////////////

static AbstractAnalyzerSubConfig *valgrindConfigFactory()
{
    return new ValgrindSettings();
}

static AbstractAnalyzerSubConfig *globalCallgrindFactory()
{
    return new CallgrindGlobalSettings();
}

static AbstractAnalyzerSubConfig *projectCallgrindFactory()
{
    return new CallgrindProjectSettings();
}

static AbstractAnalyzerSubConfig *globalMemcheckFactory()
{
    return new MemcheckGlobalSettings();
}

static AbstractAnalyzerSubConfig *projectMemcheckFactory()
{
    return new MemcheckProjectSettings();
}

bool ValgrindPlugin::initialize(const QStringList &, QString *)
{
    AnalyzerGlobalSettings::instance()->registerSubConfigs(&valgrindConfigFactory, &valgrindConfigFactory);
    AnalyzerGlobalSettings::instance()->registerSubConfigs(&globalCallgrindFactory, &projectCallgrindFactory);
    AnalyzerGlobalSettings::instance()->registerSubConfigs(&globalMemcheckFactory, &projectMemcheckFactory);

    StartModes modes;
#ifndef Q_OS_WIN
    modes.append(StartMode(StartLocal));
#endif
    modes.append(StartMode(StartRemote));

    AnalyzerManager::addTool(new MemcheckTool(this), modes);
    AnalyzerManager::addTool(new CallgrindTool(this), modes);

    return true;
}

} // namespace Internal
} // namespace Valgrind

Q_EXPORT_PLUGIN(Valgrind::Internal::ValgrindPlugin)

#include "valgrindplugin.moc"
<commit_msg>Valgrind: fix compilation<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "valgrindplugin.h"

#include "callgrindsettings.h"
#include "callgrindtool.h"
#include "memchecksettings.h"
#include "memchecktool.h"
#include "valgrindsettings.h"

#include <analyzerbase/analyzerconstants.h>
#include <analyzerbase/analyzermanager.h>

#include <utils/qtcassert.h>

#include <QtCore/QDebug>
#include <QtCore/QStringList>
#include <QtCore/QtPlugin>
#include <QtGui/QAction>

using namespace Analyzer;

namespace Valgrind {
namespace Internal {

/////////////////////////////////////////////////////////////////////////////////
//
// ValgrindPlugin
//
/////////////////////////////////////////////////////////////////////////////////

static AbstractAnalyzerSubConfig *valgrindConfigFactory()
{
    return new ValgrindSettings();
}

static AbstractAnalyzerSubConfig *globalCallgrindFactory()
{
    return new CallgrindGlobalSettings();
}

static AbstractAnalyzerSubConfig *projectCallgrindFactory()
{
    return new CallgrindProjectSettings();
}

static AbstractAnalyzerSubConfig *globalMemcheckFactory()
{
    return new MemcheckGlobalSettings();
}

static AbstractAnalyzerSubConfig *projectMemcheckFactory()
{
    return new MemcheckProjectSettings();
}

bool ValgrindPlugin::initialize(const QStringList &, QString *)
{
    AnalyzerGlobalSettings::instance()->registerSubConfigs(&valgrindConfigFactory, &valgrindConfigFactory);
    AnalyzerGlobalSettings::instance()->registerSubConfigs(&globalCallgrindFactory, &projectCallgrindFactory);
    AnalyzerGlobalSettings::instance()->registerSubConfigs(&globalMemcheckFactory, &projectMemcheckFactory);

    StartModes modes;
#ifndef Q_OS_WIN
    modes.append(StartMode(StartLocal));
#endif
    modes.append(StartMode(StartRemote));

    AnalyzerManager::addTool(new MemcheckTool(this), modes);
    AnalyzerManager::addTool(new CallgrindTool(this), modes);

    return true;
}

} // namespace Internal
} // namespace Valgrind

Q_EXPORT_PLUGIN(Valgrind::Internal::ValgrindPlugin)

<|endoftext|>


<commit_before>#include "qpreseteditordialog.hpp"
#include <QFile>
#include <QMessageBox>
#include <QKeyEvent>

QPresetEditorDialog::QPresetEditorDialog(QProjectMWidget * widget, QWidget * parent, Qt::WindowFlags f): QDialog(parent,f), _qprojectMWidget(widget) {
	_ui.setupUi(this);

	QHBoxLayout * hboxLayout = new QHBoxLayout();

	hboxLayout->addWidget(_ui.layoutWidget);
	this->setLayout(hboxLayout);

	connect(_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonBoxHandler(QAbstractButton*)));

}

void QPresetEditorDialog::setPreset(QString url, int rowIndex) {

	disconnect(_ui.presetTextEdit, 0, this, 0);

	m_index = rowIndex;

	m_presetUrl = url;
	_ui.presetTextEdit->loadPresetText(url);

	this->setWindowTitle(QString("Preset Editor - %1 [*]").arg(url));
	this->setWindowModified(false);

	connect(_ui.presetTextEdit, SIGNAL(textChanged()), this, SLOT(updateWindowTitle()));
	connect(_ui.presetTextEdit, SIGNAL(applyRequested()), this, SLOT(saveAndNotify()), Qt::DirectConnection);
}

void QPresetEditorDialog::updateWindowTitle()  {
	this->setWindowModified(true);
}

const QString & QPresetEditorDialog::presetUrl() const {
	return m_presetUrl;
}

void QPresetEditorDialog::revertBuffer() {
	setPreset(m_presetUrl, m_index);
}

void QPresetEditorDialog::saveFile() {
	QFile qfile(presetUrl());

	if (!qfile.open(QIODevice::ReadWrite | QIODevice::Text)) {
		QMessageBox::warning (0, "Preset File Error", QString(tr("There was a problem trying to save the preset \"%1\".  The file may no longer exist or you may not have permission to read the file.")).arg(presetUrl()));
		return ;
	}

	QTextStream textStream(&qfile);

	textStream << _ui.presetTextEdit->toPlainText();

	textStream.flush();
	this->setWindowModified(false);
}

void QPresetEditorDialog::saveAndNotify() {

	qDebug() << "save and notify";
	saveFile();

	emit(presetModified(m_index));
}

void QPresetEditorDialog::buttonBoxHandler(QAbstractButton * button) {
	switch (_ui.buttonBox->standardButton(button)) {
		case QDialogButtonBox::Close:
			this->hide();
			break;
		case QDialogButtonBox::Apply:
			saveAndNotify();
			break;
		case QDialogButtonBox::Reset:
			revertBuffer();
			break;
		default:
			break;
	}
}

<commit_msg>change error message<commit_after>#include "qpreseteditordialog.hpp"
#include <QFile>
#include <QMessageBox>
#include <QKeyEvent>

QPresetEditorDialog::QPresetEditorDialog(QProjectMWidget * widget, QWidget * parent, Qt::WindowFlags f): QDialog(parent,f), _qprojectMWidget(widget) {
	_ui.setupUi(this);

	QHBoxLayout * hboxLayout = new QHBoxLayout();

	hboxLayout->addWidget(_ui.layoutWidget);
	this->setLayout(hboxLayout);

	connect(_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonBoxHandler(QAbstractButton*)));

}

void QPresetEditorDialog::setPreset(QString url, int rowIndex) {

	disconnect(_ui.presetTextEdit, 0, this, 0);

	m_index = rowIndex;

	m_presetUrl = url;
	_ui.presetTextEdit->loadPresetText(url);

	this->setWindowTitle(QString("Preset Editor - %1 [*]").arg(url));
	this->setWindowModified(false);

	connect(_ui.presetTextEdit, SIGNAL(textChanged()), this, SLOT(updateWindowTitle()));
	connect(_ui.presetTextEdit, SIGNAL(applyRequested()), this, SLOT(saveAndNotify()), Qt::DirectConnection);
}

void QPresetEditorDialog::updateWindowTitle()  {
	this->setWindowModified(true);
}

const QString & QPresetEditorDialog::presetUrl() const {
	return m_presetUrl;
}

void QPresetEditorDialog::revertBuffer() {
	setPreset(m_presetUrl, m_index);
}

void QPresetEditorDialog::saveFile() {
	QFile qfile(presetUrl());

	if (!qfile.open(QIODevice::ReadWrite | QIODevice::Text)) {
		QMessageBox::warning (0, "Preset File Error", QString(tr("There was a problem trying to save the preset \"%1\".  You may not have permission to write to the file.")).arg(presetUrl()));
		return ;
	}

	QTextStream textStream(&qfile);

	textStream << _ui.presetTextEdit->toPlainText();

	textStream.flush();
	this->setWindowModified(false);
}

void QPresetEditorDialog::saveAndNotify() {

	qDebug() << "save and notify";
	saveFile();

	emit(presetModified(m_index));
}

void QPresetEditorDialog::buttonBoxHandler(QAbstractButton * button) {
	switch (_ui.buttonBox->standardButton(button)) {
		case QDialogButtonBox::Close:
			this->hide();
			break;
		case QDialogButtonBox::Apply:
			saveAndNotify();
			break;
		case QDialogButtonBox::Reset:
			revertBuffer();
			break;
		default:
			break;
	}
}

<|endoftext|>


<commit_before>
/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBufferAllocPool.h"
#include "GrTypes.h"
#include "GrVertexBuffer.h"
#include "GrIndexBuffer.h"
#include "GrGpu.h"

#if GR_DEBUG
    #define VALIDATE validate
#else
    static void VALIDATE(bool x = false) {}
#endif

// page size
#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)

GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
                                     BufferType bufferType,
                                     bool frequentResetHint,
                                     size_t blockSize,
                                     int preallocBufferCnt) :
        fBlocks(GrMax(8, 2*preallocBufferCnt)) {

    GrAssert(NULL != gpu);
    fGpu = gpu;
    fGpu->ref();
    fGpuIsReffed = true;

    fBufferType = bufferType;
    fFrequentResetHint = frequentResetHint;
    fBufferPtr = NULL;
    fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);

    fBytesInUse = 0;

    fPreallocBuffersInUse = 0;
    fFirstPreallocBuffer = 0;
    for (int i = 0; i < preallocBufferCnt; ++i) {
        GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
        if (NULL != buffer) {
            *fPreallocBuffers.append() = buffer;
            buffer->ref();
        }
    }
}

GrBufferAllocPool::~GrBufferAllocPool() {
    VALIDATE();
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    fPreallocBuffers.unrefAll();
    releaseGpuRef();
}

void GrBufferAllocPool::releaseGpuRef() {
    if (fGpuIsReffed) {
        fGpu->unref();
        fGpuIsReffed = false;
    }
}

void GrBufferAllocPool::reset() {
    VALIDATE();
    fBytesInUse = 0;
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    if (fPreallocBuffers.count()) {
        // must set this after above loop.
        fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
                               fPreallocBuffers.count();
    }
    // we may have created a large cpu mirror of a large VB. Reset the size
    // to match our pre-allocated VBs.
    fCpuData.reset(fMinBlockSize);
    GrAssert(0 == fPreallocBuffersInUse);
    VALIDATE();
}

void GrBufferAllocPool::unlock() {
    VALIDATE();

    if (NULL != fBufferPtr) {
        BufferBlock& block = fBlocks.back();
        if (block.fBuffer->isLocked()) {
            block.fBuffer->unlock();
        } else {
            size_t flushSize = block.fBuffer->sizeInBytes() - block.fBytesFree;
            flushCpuData(fBlocks.back().fBuffer, flushSize);
        }
        fBufferPtr = NULL;
    }
    VALIDATE();
}

#if GR_DEBUG
void GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        if (fBlocks.back().fBuffer->isLocked()) {
            GrGeometryBuffer* buf = fBlocks.back().fBuffer;
            GrAssert(buf->lockPtr() == fBufferPtr);
        } else {
            GrAssert(fCpuData.get() == fBufferPtr);
        }
    } else {
        GrAssert(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
    }
    size_t bytesInUse = 0;
    for (int i = 0; i < fBlocks.count() - 1; ++i) {
        GrAssert(!fBlocks[i].fBuffer->isLocked());
    }
    for (int i = 0; i < fBlocks.count(); ++i) {
        size_t bytes = fBlocks[i].fBuffer->sizeInBytes() - fBlocks[i].fBytesFree;
        bytesInUse += bytes;
        GrAssert(bytes || unusedBlockAllowed);
    }

    GrAssert(bytesInUse == fBytesInUse);
    if (unusedBlockAllowed) {
        GrAssert((fBytesInUse && !fBlocks.empty()) ||
                 (!fBytesInUse && (fBlocks.count() < 2)));
    } else {
        GrAssert((0 == fBytesInUse) == fBlocks.empty());
    }
}
#endif

void* GrBufferAllocPool::makeSpace(size_t size,
                                   size_t alignment,
                                   const GrGeometryBuffer** buffer,
                                   size_t* offset) {
    VALIDATE();

    GrAssert(NULL != buffer);
    GrAssert(NULL != offset);

    if (NULL != fBufferPtr) {
        BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes,
                                      alignment);
        if ((size + pad) <= back.fBytesFree) {
            usedBytes += pad;
            *offset = usedBytes;
            *buffer = back.fBuffer;
            back.fBytesFree -= size + pad;
            fBytesInUse += size;
            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
        }
    }

    // We could honor the space request using by a partial update of the current
    // VB (if there is room). But we don't currently use draw calls to GL that
    // allow the driver to know that previously issued draws won't read from
    // the part of the buffer we update. Also, the GL buffer implementation
    // may be cheating on the actual buffer size by shrinking the buffer on
    // updateData() if the amount of data passed is less than the full buffer
    // size.

    if (!createBlock(size)) {
        return NULL;
    }
    GrAssert(NULL != fBufferPtr);

    *offset = 0;
    BufferBlock& back = fBlocks.back();
    *buffer = back.fBuffer;
    back.fBytesFree -= size;
    fBytesInUse += size;
    VALIDATE();
    return fBufferPtr;
}

int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
    VALIDATE();
    if (NULL != fBufferPtr) {
        const BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
        return (back.fBytesFree - pad) / itemSize;
    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
        return fMinBlockSize / itemSize;
    }
    return 0;
}

int GrBufferAllocPool::preallocatedBuffersRemaining() const {
    return fPreallocBuffers.count() - fPreallocBuffersInUse;
}

int GrBufferAllocPool::preallocatedBufferCount() const {
    return fPreallocBuffers.count();
}

void GrBufferAllocPool::putBack(size_t bytes) {
    VALIDATE();

    while (bytes) {
        // caller shouldnt try to put back more than they've taken
        GrAssert(!fBlocks.empty());
        BufferBlock& block = fBlocks.back();
        size_t bytesUsed = block.fBuffer->sizeInBytes() - block.fBytesFree;
        if (bytes >= bytesUsed) {
            bytes -= bytesUsed;
            fBytesInUse -= bytesUsed;
            // if we locked a vb to satisfy the make space and we're releasing
            // beyond it, then unlock it.
            if (block.fBuffer->isLocked()) {
                block.fBuffer->unlock();
            }
            this->destroyBlock();
        } else {
            block.fBytesFree += bytes;
            fBytesInUse -= bytes;
            bytes = 0;
            break;
        }
    }
    VALIDATE();
}

bool GrBufferAllocPool::createBlock(size_t requestSize) {

    size_t size = GrMax(requestSize, fMinBlockSize);
    GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);

    VALIDATE();

    BufferBlock& block = fBlocks.push_back();

    if (size == fMinBlockSize &&
        fPreallocBuffersInUse < fPreallocBuffers.count()) {

        uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
                               fPreallocBuffers.count();
        block.fBuffer = fPreallocBuffers[nextBuffer];
        block.fBuffer->ref();
        ++fPreallocBuffersInUse;
    } else {
        block.fBuffer = this->createBuffer(size);
        if (NULL == block.fBuffer) {
            fBlocks.pop_back();
            return false;
        }
    }

    block.fBytesFree = size;
    if (NULL != fBufferPtr) {
        GrAssert(fBlocks.count() > 1);
        BufferBlock& prev = fBlocks.fromBack(1);
        if (prev.fBuffer->isLocked()) {
            prev.fBuffer->unlock();
        } else {
            flushCpuData(prev.fBuffer,
                         prev.fBuffer->sizeInBytes() - prev.fBytesFree);
        }
        fBufferPtr = NULL;
    }

    GrAssert(NULL == fBufferPtr);

    if (fGpu->getCaps().fBufferLockSupport &&
        size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
        (!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
        fBufferPtr = block.fBuffer->lock();
    }

    if (NULL == fBufferPtr) {
        fBufferPtr = fCpuData.reset(size);
    }

    VALIDATE(true);

    return true;
}

void GrBufferAllocPool::destroyBlock() {
    GrAssert(!fBlocks.empty());

    BufferBlock& block = fBlocks.back();
    if (fPreallocBuffersInUse > 0) {
        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
                                       fFirstPreallocBuffer +
                                       (fPreallocBuffers.count() - 1)) %
                                      fPreallocBuffers.count();
        if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
            --fPreallocBuffersInUse;
        }
    }
    GrAssert(!block.fBuffer->isLocked());
    block.fBuffer->unref();
    fBlocks.pop_back();
    fBufferPtr = NULL;
}

void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
                                     size_t flushSize) {
    GrAssert(NULL != buffer);
    GrAssert(!buffer->isLocked());
    GrAssert(fCpuData.get() == fBufferPtr);
    GrAssert(flushSize <= buffer->sizeInBytes());

    if (fGpu->getCaps().fBufferLockSupport &&
        flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
        void* data = buffer->lock();
        if (NULL != data) {
            memcpy(data, fBufferPtr, flushSize);
            buffer->unlock();
            return;
        }
    }
    buffer->updateData(fBufferPtr, flushSize);
}

GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
    if (kIndex_BufferType == fBufferType) {
        return fGpu->createIndexBuffer(size, true);
    } else {
        GrAssert(kVertex_BufferType == fBufferType);
        return fGpu->createVertexBuffer(size, true);
    }
}

////////////////////////////////////////////////////////////////////////////////

GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
                                                 bool frequentResetHint,
                                                 size_t bufferSize,
                                                 int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kVertex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrVertexBufferAllocPool::makeSpace(GrVertexLayout layout,
                                         int vertexCount,
                                         const GrVertexBuffer** buffer,
                                         int* startVertex) {

    GrAssert(vertexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startVertex);

    size_t vSize = GrDrawTarget::VertexSize(layout);
    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(vSize * vertexCount,
                                     vSize,
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrVertexBuffer*) geomBuffer;
    GrAssert(0 == offset % vSize);
    *startVertex = offset / vSize;
    return ptr;
}

bool GrVertexBufferAllocPool::appendVertices(GrVertexLayout layout,
                                             int vertexCount,
                                             const void* vertices,
                                             const GrVertexBuffer** buffer,
                                             int* startVertex) {
    void* space = makeSpace(layout, vertexCount, buffer, startVertex);
    if (NULL != space) {
        memcpy(space,
               vertices,
               GrDrawTarget::VertexSize(layout) * vertexCount);
        return true;
    } else {
        return false;
    }
}

int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
    return INHERITED::preallocatedBufferSize() /
            GrDrawTarget::VertexSize(layout);
}

int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
    return currentBufferItems(GrDrawTarget::VertexSize(layout));
}

////////////////////////////////////////////////////////////////////////////////

GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
                                               bool frequentResetHint,
                                               size_t bufferSize,
                                               int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kIndex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrIndexBufferAllocPool::makeSpace(int indexCount,
                                        const GrIndexBuffer** buffer,
                                        int* startIndex) {

    GrAssert(indexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startIndex);

    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
                                     sizeof(uint16_t),
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrIndexBuffer*) geomBuffer;
    GrAssert(0 == offset % sizeof(uint16_t));
    *startIndex = offset / sizeof(uint16_t);
    return ptr;
}

bool GrIndexBufferAllocPool::appendIndices(int indexCount,
                                           const void* indices,
                                           const GrIndexBuffer** buffer,
                                           int* startIndex) {
    void* space = makeSpace(indexCount, buffer, startIndex);
    if (NULL != space) {
        memcpy(space, indices, sizeof(uint16_t) * indexCount);
        return true;
    } else {
        return false;
    }
}

int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
    return INHERITED::preallocatedBufferSize() / sizeof(uint16_t);
}

int GrIndexBufferAllocPool::currentBufferIndices() const {
    return currentBufferItems(sizeof(uint16_t));
}
<commit_msg>Remove ref in buffer alloc pool.<commit_after>
/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrBufferAllocPool.h"
#include "GrTypes.h"
#include "GrVertexBuffer.h"
#include "GrIndexBuffer.h"
#include "GrGpu.h"

#if GR_DEBUG
    #define VALIDATE validate
#else
    static void VALIDATE(bool x = false) {}
#endif

// page size
#define GrBufferAllocPool_MIN_BLOCK_SIZE ((size_t)1 << 12)

GrBufferAllocPool::GrBufferAllocPool(GrGpu* gpu,
                                     BufferType bufferType,
                                     bool frequentResetHint,
                                     size_t blockSize,
                                     int preallocBufferCnt) :
        fBlocks(GrMax(8, 2*preallocBufferCnt)) {

    GrAssert(NULL != gpu);
    fGpu = gpu;
    fGpu->ref();
    fGpuIsReffed = true;

    fBufferType = bufferType;
    fFrequentResetHint = frequentResetHint;
    fBufferPtr = NULL;
    fMinBlockSize = GrMax(GrBufferAllocPool_MIN_BLOCK_SIZE, blockSize);

    fBytesInUse = 0;

    fPreallocBuffersInUse = 0;
    fFirstPreallocBuffer = 0;
    for (int i = 0; i < preallocBufferCnt; ++i) {
        GrGeometryBuffer* buffer = this->createBuffer(fMinBlockSize);
        if (NULL != buffer) {
            *fPreallocBuffers.append() = buffer;
        }
    }
}

GrBufferAllocPool::~GrBufferAllocPool() {
    VALIDATE();
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    fPreallocBuffers.unrefAll();
    releaseGpuRef();
}

void GrBufferAllocPool::releaseGpuRef() {
    if (fGpuIsReffed) {
        fGpu->unref();
        fGpuIsReffed = false;
    }
}

void GrBufferAllocPool::reset() {
    VALIDATE();
    fBytesInUse = 0;
    if (fBlocks.count()) {
        GrGeometryBuffer* buffer = fBlocks.back().fBuffer;
        if (buffer->isLocked()) {
            buffer->unlock();
        }
    }
    while (!fBlocks.empty()) {
        destroyBlock();
    }
    if (fPreallocBuffers.count()) {
        // must set this after above loop.
        fFirstPreallocBuffer = (fFirstPreallocBuffer + fPreallocBuffersInUse) %
                               fPreallocBuffers.count();
    }
    // we may have created a large cpu mirror of a large VB. Reset the size
    // to match our pre-allocated VBs.
    fCpuData.reset(fMinBlockSize);
    GrAssert(0 == fPreallocBuffersInUse);
    VALIDATE();
}

void GrBufferAllocPool::unlock() {
    VALIDATE();

    if (NULL != fBufferPtr) {
        BufferBlock& block = fBlocks.back();
        if (block.fBuffer->isLocked()) {
            block.fBuffer->unlock();
        } else {
            size_t flushSize = block.fBuffer->sizeInBytes() - block.fBytesFree;
            flushCpuData(fBlocks.back().fBuffer, flushSize);
        }
        fBufferPtr = NULL;
    }
    VALIDATE();
}

#if GR_DEBUG
void GrBufferAllocPool::validate(bool unusedBlockAllowed) const {
    if (NULL != fBufferPtr) {
        GrAssert(!fBlocks.empty());
        if (fBlocks.back().fBuffer->isLocked()) {
            GrGeometryBuffer* buf = fBlocks.back().fBuffer;
            GrAssert(buf->lockPtr() == fBufferPtr);
        } else {
            GrAssert(fCpuData.get() == fBufferPtr);
        }
    } else {
        GrAssert(fBlocks.empty() || !fBlocks.back().fBuffer->isLocked());
    }
    size_t bytesInUse = 0;
    for (int i = 0; i < fBlocks.count() - 1; ++i) {
        GrAssert(!fBlocks[i].fBuffer->isLocked());
    }
    for (int i = 0; i < fBlocks.count(); ++i) {
        size_t bytes = fBlocks[i].fBuffer->sizeInBytes() - fBlocks[i].fBytesFree;
        bytesInUse += bytes;
        GrAssert(bytes || unusedBlockAllowed);
    }

    GrAssert(bytesInUse == fBytesInUse);
    if (unusedBlockAllowed) {
        GrAssert((fBytesInUse && !fBlocks.empty()) ||
                 (!fBytesInUse && (fBlocks.count() < 2)));
    } else {
        GrAssert((0 == fBytesInUse) == fBlocks.empty());
    }
}
#endif

void* GrBufferAllocPool::makeSpace(size_t size,
                                   size_t alignment,
                                   const GrGeometryBuffer** buffer,
                                   size_t* offset) {
    VALIDATE();

    GrAssert(NULL != buffer);
    GrAssert(NULL != offset);

    if (NULL != fBufferPtr) {
        BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes,
                                      alignment);
        if ((size + pad) <= back.fBytesFree) {
            usedBytes += pad;
            *offset = usedBytes;
            *buffer = back.fBuffer;
            back.fBytesFree -= size + pad;
            fBytesInUse += size;
            return (void*)(reinterpret_cast<intptr_t>(fBufferPtr) + usedBytes);
        }
    }

    // We could honor the space request using by a partial update of the current
    // VB (if there is room). But we don't currently use draw calls to GL that
    // allow the driver to know that previously issued draws won't read from
    // the part of the buffer we update. Also, the GL buffer implementation
    // may be cheating on the actual buffer size by shrinking the buffer on
    // updateData() if the amount of data passed is less than the full buffer
    // size.

    if (!createBlock(size)) {
        return NULL;
    }
    GrAssert(NULL != fBufferPtr);

    *offset = 0;
    BufferBlock& back = fBlocks.back();
    *buffer = back.fBuffer;
    back.fBytesFree -= size;
    fBytesInUse += size;
    VALIDATE();
    return fBufferPtr;
}

int GrBufferAllocPool::currentBufferItems(size_t itemSize) const {
    VALIDATE();
    if (NULL != fBufferPtr) {
        const BufferBlock& back = fBlocks.back();
        size_t usedBytes = back.fBuffer->sizeInBytes() - back.fBytesFree;
        size_t pad = GrSizeAlignUpPad(usedBytes, itemSize);
        return (back.fBytesFree - pad) / itemSize;
    } else if (fPreallocBuffersInUse < fPreallocBuffers.count()) {
        return fMinBlockSize / itemSize;
    }
    return 0;
}

int GrBufferAllocPool::preallocatedBuffersRemaining() const {
    return fPreallocBuffers.count() - fPreallocBuffersInUse;
}

int GrBufferAllocPool::preallocatedBufferCount() const {
    return fPreallocBuffers.count();
}

void GrBufferAllocPool::putBack(size_t bytes) {
    VALIDATE();

    while (bytes) {
        // caller shouldnt try to put back more than they've taken
        GrAssert(!fBlocks.empty());
        BufferBlock& block = fBlocks.back();
        size_t bytesUsed = block.fBuffer->sizeInBytes() - block.fBytesFree;
        if (bytes >= bytesUsed) {
            bytes -= bytesUsed;
            fBytesInUse -= bytesUsed;
            // if we locked a vb to satisfy the make space and we're releasing
            // beyond it, then unlock it.
            if (block.fBuffer->isLocked()) {
                block.fBuffer->unlock();
            }
            this->destroyBlock();
        } else {
            block.fBytesFree += bytes;
            fBytesInUse -= bytes;
            bytes = 0;
            break;
        }
    }
    VALIDATE();
}

bool GrBufferAllocPool::createBlock(size_t requestSize) {

    size_t size = GrMax(requestSize, fMinBlockSize);
    GrAssert(size >= GrBufferAllocPool_MIN_BLOCK_SIZE);

    VALIDATE();

    BufferBlock& block = fBlocks.push_back();

    if (size == fMinBlockSize &&
        fPreallocBuffersInUse < fPreallocBuffers.count()) {

        uint32_t nextBuffer = (fPreallocBuffersInUse + fFirstPreallocBuffer) %
                               fPreallocBuffers.count();
        block.fBuffer = fPreallocBuffers[nextBuffer];
        block.fBuffer->ref();
        ++fPreallocBuffersInUse;
    } else {
        block.fBuffer = this->createBuffer(size);
        if (NULL == block.fBuffer) {
            fBlocks.pop_back();
            return false;
        }
    }

    block.fBytesFree = size;
    if (NULL != fBufferPtr) {
        GrAssert(fBlocks.count() > 1);
        BufferBlock& prev = fBlocks.fromBack(1);
        if (prev.fBuffer->isLocked()) {
            prev.fBuffer->unlock();
        } else {
            flushCpuData(prev.fBuffer,
                         prev.fBuffer->sizeInBytes() - prev.fBytesFree);
        }
        fBufferPtr = NULL;
    }

    GrAssert(NULL == fBufferPtr);

    if (fGpu->getCaps().fBufferLockSupport &&
        size > GR_GEOM_BUFFER_LOCK_THRESHOLD &&
        (!fFrequentResetHint || requestSize > GR_GEOM_BUFFER_LOCK_THRESHOLD)) {
        fBufferPtr = block.fBuffer->lock();
    }

    if (NULL == fBufferPtr) {
        fBufferPtr = fCpuData.reset(size);
    }

    VALIDATE(true);

    return true;
}

void GrBufferAllocPool::destroyBlock() {
    GrAssert(!fBlocks.empty());

    BufferBlock& block = fBlocks.back();
    if (fPreallocBuffersInUse > 0) {
        uint32_t prevPreallocBuffer = (fPreallocBuffersInUse +
                                       fFirstPreallocBuffer +
                                       (fPreallocBuffers.count() - 1)) %
                                      fPreallocBuffers.count();
        if (block.fBuffer == fPreallocBuffers[prevPreallocBuffer]) {
            --fPreallocBuffersInUse;
        }
    }
    GrAssert(!block.fBuffer->isLocked());
    block.fBuffer->unref();
    fBlocks.pop_back();
    fBufferPtr = NULL;
}

void GrBufferAllocPool::flushCpuData(GrGeometryBuffer* buffer,
                                     size_t flushSize) {
    GrAssert(NULL != buffer);
    GrAssert(!buffer->isLocked());
    GrAssert(fCpuData.get() == fBufferPtr);
    GrAssert(flushSize <= buffer->sizeInBytes());

    if (fGpu->getCaps().fBufferLockSupport &&
        flushSize > GR_GEOM_BUFFER_LOCK_THRESHOLD) {
        void* data = buffer->lock();
        if (NULL != data) {
            memcpy(data, fBufferPtr, flushSize);
            buffer->unlock();
            return;
        }
    }
    buffer->updateData(fBufferPtr, flushSize);
}

GrGeometryBuffer* GrBufferAllocPool::createBuffer(size_t size) {
    if (kIndex_BufferType == fBufferType) {
        return fGpu->createIndexBuffer(size, true);
    } else {
        GrAssert(kVertex_BufferType == fBufferType);
        return fGpu->createVertexBuffer(size, true);
    }
}

////////////////////////////////////////////////////////////////////////////////

GrVertexBufferAllocPool::GrVertexBufferAllocPool(GrGpu* gpu,
                                                 bool frequentResetHint,
                                                 size_t bufferSize,
                                                 int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kVertex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrVertexBufferAllocPool::makeSpace(GrVertexLayout layout,
                                         int vertexCount,
                                         const GrVertexBuffer** buffer,
                                         int* startVertex) {

    GrAssert(vertexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startVertex);

    size_t vSize = GrDrawTarget::VertexSize(layout);
    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(vSize * vertexCount,
                                     vSize,
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrVertexBuffer*) geomBuffer;
    GrAssert(0 == offset % vSize);
    *startVertex = offset / vSize;
    return ptr;
}

bool GrVertexBufferAllocPool::appendVertices(GrVertexLayout layout,
                                             int vertexCount,
                                             const void* vertices,
                                             const GrVertexBuffer** buffer,
                                             int* startVertex) {
    void* space = makeSpace(layout, vertexCount, buffer, startVertex);
    if (NULL != space) {
        memcpy(space,
               vertices,
               GrDrawTarget::VertexSize(layout) * vertexCount);
        return true;
    } else {
        return false;
    }
}

int GrVertexBufferAllocPool::preallocatedBufferVertices(GrVertexLayout layout) const {
    return INHERITED::preallocatedBufferSize() /
            GrDrawTarget::VertexSize(layout);
}

int GrVertexBufferAllocPool::currentBufferVertices(GrVertexLayout layout) const {
    return currentBufferItems(GrDrawTarget::VertexSize(layout));
}

////////////////////////////////////////////////////////////////////////////////

GrIndexBufferAllocPool::GrIndexBufferAllocPool(GrGpu* gpu,
                                               bool frequentResetHint,
                                               size_t bufferSize,
                                               int preallocBufferCnt)
: GrBufferAllocPool(gpu,
                    kIndex_BufferType,
                    frequentResetHint,
                    bufferSize,
                    preallocBufferCnt) {
}

void* GrIndexBufferAllocPool::makeSpace(int indexCount,
                                        const GrIndexBuffer** buffer,
                                        int* startIndex) {

    GrAssert(indexCount >= 0);
    GrAssert(NULL != buffer);
    GrAssert(NULL != startIndex);

    size_t offset = 0; // assign to suppress warning
    const GrGeometryBuffer* geomBuffer = NULL; // assign to suppress warning
    void* ptr = INHERITED::makeSpace(indexCount * sizeof(uint16_t),
                                     sizeof(uint16_t),
                                     &geomBuffer,
                                     &offset);

    *buffer = (const GrIndexBuffer*) geomBuffer;
    GrAssert(0 == offset % sizeof(uint16_t));
    *startIndex = offset / sizeof(uint16_t);
    return ptr;
}

bool GrIndexBufferAllocPool::appendIndices(int indexCount,
                                           const void* indices,
                                           const GrIndexBuffer** buffer,
                                           int* startIndex) {
    void* space = makeSpace(indexCount, buffer, startIndex);
    if (NULL != space) {
        memcpy(space, indices, sizeof(uint16_t) * indexCount);
        return true;
    } else {
        return false;
    }
}

int GrIndexBufferAllocPool::preallocatedBufferIndices() const {
    return INHERITED::preallocatedBufferSize() / sizeof(uint16_t);
}

int GrIndexBufferAllocPool::currentBufferIndices() const {
    return currentBufferItems(sizeof(uint16_t));
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The Karbowanec developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "SignMessageDialog.h"
#include "ui_signmessagedialog.h"

#include <QClipboard>
#include <QFileDialog>
#include <QTextStream>
#include <QTabWidget>

#include "Common/Base58.h"
#include "Common/StringTools.h"
#include "CurrencyAdapter.h"
#include "WalletAdapter.h"
#include "MainWindow.h"
#include <boost/utility/value_init.hpp>
#include "crypto/crypto.h"

namespace WalletGui {

SignMessageDialog::SignMessageDialog(QWidget* _parent) : QDialog(_parent), m_ui(new Ui::SignMessageDialog) {
  m_ui->setupUi(this);
  connect(&WalletAdapter::instance(), &WalletAdapter::walletInitCompletedSignal, this, &SignMessageDialog::walletOpened, Qt::QueuedConnection);
  connect(&WalletAdapter::instance(), &WalletAdapter::walletCloseCompletedSignal, this, &SignMessageDialog::walletClosed, Qt::QueuedConnection);
  m_ui->m_verificationResult->setText("");
}

SignMessageDialog::~SignMessageDialog() {
}

void SignMessageDialog::sign() {
  m_ui->m_tabWidget->setCurrentIndex(0);
  changeTitle(0);
}

void SignMessageDialog::verify() {
  m_ui->m_tabWidget->setCurrentIndex(1);
  changeTitle(1);
}

void SignMessageDialog::changeTitle(int _variant) {
  this->setWindowTitle(_variant == 0 ? tr("Sign message") : tr("Verify signed message"));
}

void SignMessageDialog::walletOpened() {
  m_address = WalletAdapter::instance().getAddress();
}

void SignMessageDialog::walletClosed() {
  m_ui->m_messageEdit->clear();
}

void SignMessageDialog::messageChanged() {
  std::string message = m_ui->m_messageEdit->toPlainText().toUtf8().constData();
  Crypto::Hash hash;
  Crypto::cn_fast_hash(message.data(), message.size(), hash);
  CryptoNote::AccountKeys keys;
  WalletAdapter::instance().getAccountKeys(keys);
  Crypto::Signature signature;
  Crypto::generate_signature(hash, keys.address.spendPublicKey, keys.spendSecretKey, signature);
  QString sig = QString::fromStdString(std::string("SigV1") + Tools::Base58::encode(std::string((const char *)&signature, sizeof(signature))));
  m_ui->m_signatureEdit->setText(sig);
}

void SignMessageDialog::verifyMessage() {
  m_ui->m_verificationResult->setText("");
  CryptoNote::AccountPublicAddress acc = boost::value_initialized<CryptoNote::AccountPublicAddress>();
  std::string addr_str = m_ui->m_addressEdit->text().trimmed().toStdString();
  if(!addr_str.empty()) {
    if(CurrencyAdapter::instance().getCurrency().parseAccountAddressString(addr_str, acc)) {
      std::string message = m_ui->m_verifyMessageEdit->toPlainText().toUtf8().constData();
      if(!message.empty()) {
        Crypto::Hash hash;
        Crypto::cn_fast_hash(message.data(), message.size(), hash);
        std::string signature = m_ui->m_verifySignatureEdit->toPlainText().toStdString();
        const size_t header_len = strlen("SigV1");
        if (!signature.size() < header_len || signature.substr(0, header_len) == "SigV1") {
          std::string decoded;
          Crypto::Signature s;
          if (Tools::Base58::decode(signature.substr(header_len), decoded) || sizeof(s) == decoded.size()) {
            memcpy(&s, decoded.data(), sizeof(s));
            bool valid = Crypto::check_signature(hash, acc.spendPublicKey, s);
            if (valid) {
              m_ui->m_verificationResult->setText(tr("Signature is valid"));
              m_ui->m_verificationResult->setStyleSheet("QLabel { color : green; }");
            } else {
              m_ui->m_verificationResult->setText(tr("Signature is invalid!"));
              m_ui->m_verificationResult->setStyleSheet("QLabel { color : red; }");
            }
          }
        }
      }
    }
  }
}

}
<commit_msg>Fix crash in Verify message dialog<commit_after>// Copyright (c) 2016 The Karbowanec developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "SignMessageDialog.h"
#include "ui_signmessagedialog.h"

#include <QClipboard>
#include <QFileDialog>
#include <QTextStream>
#include <QTabWidget>

#include "Common/Base58.h"
#include "Common/StringTools.h"
#include "CurrencyAdapter.h"
#include "WalletAdapter.h"
#include "MainWindow.h"
#include <boost/utility/value_init.hpp>
#include "crypto/crypto.h"

namespace WalletGui {

SignMessageDialog::SignMessageDialog(QWidget* _parent) : QDialog(_parent), m_ui(new Ui::SignMessageDialog) {
  m_ui->setupUi(this);
  connect(&WalletAdapter::instance(), &WalletAdapter::walletInitCompletedSignal, this, &SignMessageDialog::walletOpened, Qt::QueuedConnection);
  connect(&WalletAdapter::instance(), &WalletAdapter::walletCloseCompletedSignal, this, &SignMessageDialog::walletClosed, Qt::QueuedConnection);
  m_ui->m_verificationResult->setText("");
}

SignMessageDialog::~SignMessageDialog() {
}

void SignMessageDialog::sign() {
  m_ui->m_tabWidget->setCurrentIndex(0);
  changeTitle(0);
}

void SignMessageDialog::verify() {
  m_ui->m_tabWidget->setCurrentIndex(1);
  changeTitle(1);
}

void SignMessageDialog::changeTitle(int _variant) {
  this->setWindowTitle(_variant == 0 ? tr("Sign message") : tr("Verify signed message"));
}

void SignMessageDialog::walletOpened() {
  m_address = WalletAdapter::instance().getAddress();
}

void SignMessageDialog::walletClosed() {
  m_ui->m_messageEdit->clear();
}

void SignMessageDialog::messageChanged() {
  if (m_ui->m_tabWidget->currentIndex() != 0) { return; }
  std::string message = m_ui->m_messageEdit->toPlainText().toUtf8().constData();
  Crypto::Hash hash;
  Crypto::cn_fast_hash(message.data(), message.size(), hash);
  CryptoNote::AccountKeys keys;
  WalletAdapter::instance().getAccountKeys(keys);
  Crypto::Signature signature;
  Crypto::generate_signature(hash, keys.address.spendPublicKey, keys.spendSecretKey, signature);
  QString sig = QString::fromStdString(std::string("SigV1") + Tools::Base58::encode(std::string((const char *)&signature, sizeof(signature))));
  m_ui->m_signatureEdit->setText(sig);
}

void SignMessageDialog::verifyMessage() {
  m_ui->m_verificationResult->setText("");
  CryptoNote::AccountPublicAddress acc = boost::value_initialized<CryptoNote::AccountPublicAddress>();
  std::string addr_str = m_ui->m_addressEdit->text().trimmed().toStdString();
  if(!addr_str.empty()) {
    if(CurrencyAdapter::instance().getCurrency().parseAccountAddressString(addr_str, acc)) {
      std::string message = m_ui->m_verifyMessageEdit->toPlainText().toUtf8().constData();
      if(!message.empty()) {
        Crypto::Hash hash;
        Crypto::cn_fast_hash(message.data(), message.size(), hash);
        std::string signature = m_ui->m_verifySignatureEdit->toPlainText().toStdString();
        const size_t header_len = strlen("SigV1");
        if (!signature.size() < header_len || signature.substr(0, header_len) == "SigV1") {
          std::string decoded;
          Crypto::Signature s;
          if (Tools::Base58::decode(signature.substr(header_len), decoded) || sizeof(s) == decoded.size()) {
            memcpy(&s, decoded.data(), sizeof(s));
            bool valid = Crypto::check_signature(hash, acc.spendPublicKey, s);
            if (valid) {
              m_ui->m_verificationResult->setText(tr("Signature is valid"));
              m_ui->m_verificationResult->setStyleSheet("QLabel { color : green; }");
            } else {
              m_ui->m_verificationResult->setText(tr("Signature is invalid!"));
              m_ui->m_verificationResult->setStyleSheet("QLabel { color : red; }");
            }
          }
        }
      }
    }
  }
}

}
<|endoftext|>