<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "FizzContextProvider.h"

#include <fizz/client/FizzClientContext.h>
#include <fizz/client/SynchronizedLruPskCache.h>
#include <fizz/protocol/DefaultCertificateVerifier.h>
#include <fizz/server/FizzServerContext.h>
#include <fizz/server/TicketCodec.h>
#include <fizz/server/TicketTypes.h>
#include <folly/Singleton.h>
#include <folly/ssl/Init.h>

#include "mcrouter/lib/fbi/cpp/LogFailure.h"

namespace facebook {
namespace memcache {

namespace {
void initSSL() {
  static folly::once_flag flag;
  folly::call_once(flag, [&]() { folly::ssl::init(); });
}

/* Sessions are valid for upto 24 hours */
constexpr size_t kSessionLifeTime = 86400;
/* Handshakes are valid for up to 1 week */
constexpr size_t kHandshakeValidity = 604800;
} // namespace

FizzContextAndVerifier createClientFizzContextAndVerifier(
    std::string certData,
    std::string keyData,
    folly::StringPiece pemCaPath,
    bool preferOcbCipher) {
  // global session cache
  static auto SESSION_CACHE =
      std::make_shared<fizz::client::SynchronizedLruPskCache>(100);
  initSSL();
  auto ctx = std::make_shared<fizz::client::FizzClientContext>();
  ctx->setSupportedVersions({fizz::ProtocolVersion::tls_1_3});
  ctx->setPskCache(SESSION_CACHE);

  if (!certData.empty() && !keyData.empty()) {
    auto cert =
        fizz::CertUtils::makeSelfCert(std::move(certData), std::move(keyData));
    ctx->setClientCertificate(std::move(cert));
  }
  std::shared_ptr<fizz::DefaultCertificateVerifier> verifier;
  if (!pemCaPath.empty()) {
    verifier = fizz::DefaultCertificateVerifier::createFromCAFile(
        fizz::VerificationContext::Client, pemCaPath.str());
  }

  if (preferOcbCipher) {
#if FOLLY_OPENSSL_IS_110 && !defined(OPENSSL_NO_OCB)
    auto ciphers = folly::copy(ctx->getSupportedCiphers());
    ciphers.insert(
        ciphers.begin(),
        fizz::CipherSuite::TLS_AES_128_OCB_SHA256_EXPERIMENTAL);
    ctx->setSupportedCiphers(std::move(ciphers));
#endif
  }

  return FizzContextAndVerifier(std::move(ctx), std::move(verifier));
}

std::shared_ptr<fizz::server::FizzServerContext> createFizzServerContext(
    folly::StringPiece pemCertPath,
    folly::StringPiece certData,
    folly::StringPiece pemKeyPath,
    folly::StringPiece keyData,
    folly::StringPiece pemCaPath,
    bool requireClientVerification,
    bool preferOcbCipher,
    wangle::TLSTicketKeySeeds* ticketKeySeeds) {
  initSSL();
  auto certMgr = std::make_unique<fizz::server::CertManager>();
  try {
    auto selfCert =
        fizz::CertUtils::makeSelfCert(certData.str(), keyData.str());
    // add the default cert
    certMgr->addCert(std::move(selfCert), true);
  } catch (const std::exception& ex) {
    LOG_FAILURE(
        "SSLCert",
        failure::Category::kBadEnvironment,
        "Failed to create self cert from \"{}\" and \"{}\".  ex: {}",
        pemCertPath,
        pemKeyPath,
        ex.what());
    return nullptr;
  }

  auto ctx = std::make_shared<fizz::server::FizzServerContext>();
  ctx->setSupportedVersions({fizz::ProtocolVersion::tls_1_3});
  ctx->setSupportedPskModes(
      {fizz::PskKeyExchangeMode::psk_ke, fizz::PskKeyExchangeMode::psk_dhe_ke});
  ctx->setVersionFallbackEnabled(true);
  ctx->setCertManager(std::move(certMgr));
  if (!pemCaPath.empty()) {
    auto verifier = fizz::DefaultCertificateVerifier::createFromCAFile(
        fizz::VerificationContext::Server, pemCaPath.str());
    ctx->setClientCertVerifier(std::move(verifier));
    ctx->setClientAuthMode(fizz::server::ClientAuthMode::Optional);
  }
  if (requireClientVerification) {
    ctx->setClientAuthMode(fizz::server::ClientAuthMode::Required);
  }
  if (preferOcbCipher) {
#if FOLLY_OPENSSL_IS_110 && !defined(OPENSSL_NO_OCB)
    auto serverCiphers = folly::copy(ctx->getSupportedCiphers());
    serverCiphers.insert(
        serverCiphers.begin(),
        {
            fizz::CipherSuite::TLS_AES_128_OCB_SHA256_EXPERIMENTAL,
        });
    ctx->setSupportedCiphers(std::move(serverCiphers));
#endif
  }

  // set ticket seeds
  if (ticketKeySeeds) {
    std::vector<folly::ByteRange> ticketSecrets;
    for (const auto& secret : ticketKeySeeds->currentSeeds) {
      ticketSecrets.push_back(folly::StringPiece(secret));
    }
    for (const auto& secret : ticketKeySeeds->oldSeeds) {
      ticketSecrets.push_back(folly::StringPiece(secret));
    }
    for (const auto& secret : ticketKeySeeds->newSeeds) {
      ticketSecrets.push_back(folly::StringPiece(secret));
    }
    auto cipher = std::make_shared<fizz::server::AES128TicketCipher>();
    cipher->setTicketSecrets(std::move(ticketSecrets));
    cipher->setTicketValidity(std::chrono::seconds(kSessionLifeTime));
    cipher->setHandshakeValidity(std::chrono::seconds(kHandshakeValidity));
    ctx->setTicketCipher(std::move(cipher));
  }
  // TODO: allow for custom FizzFactory
  return ctx;
}
} // namespace memcache
} // namespace facebook
<commit_msg>Refactoring AeadTicketCipher to use TicketPolicy instead of tracking time directly<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "FizzContextProvider.h"

#include <fizz/client/FizzClientContext.h>
#include <fizz/client/SynchronizedLruPskCache.h>
#include <fizz/protocol/DefaultCertificateVerifier.h>
#include <fizz/server/FizzServerContext.h>
#include <fizz/server/TicketCodec.h>
#include <fizz/server/TicketTypes.h>
#include <folly/Singleton.h>
#include <folly/ssl/Init.h>

#include "mcrouter/lib/fbi/cpp/LogFailure.h"

namespace facebook {
namespace memcache {

namespace {
void initSSL() {
  static folly::once_flag flag;
  folly::call_once(flag, [&]() { folly::ssl::init(); });
}

/* Sessions are valid for upto 24 hours */
constexpr size_t kSessionLifeTime = 86400;
/* Handshakes are valid for up to 1 week */
constexpr size_t kHandshakeValidity = 604800;
} // namespace

FizzContextAndVerifier createClientFizzContextAndVerifier(
    std::string certData,
    std::string keyData,
    folly::StringPiece pemCaPath,
    bool preferOcbCipher) {
  // global session cache
  static auto SESSION_CACHE =
      std::make_shared<fizz::client::SynchronizedLruPskCache>(100);
  initSSL();
  auto ctx = std::make_shared<fizz::client::FizzClientContext>();
  ctx->setSupportedVersions({fizz::ProtocolVersion::tls_1_3});
  ctx->setPskCache(SESSION_CACHE);

  if (!certData.empty() && !keyData.empty()) {
    auto cert =
        fizz::CertUtils::makeSelfCert(std::move(certData), std::move(keyData));
    ctx->setClientCertificate(std::move(cert));
  }
  std::shared_ptr<fizz::DefaultCertificateVerifier> verifier;
  if (!pemCaPath.empty()) {
    verifier = fizz::DefaultCertificateVerifier::createFromCAFile(
        fizz::VerificationContext::Client, pemCaPath.str());
  }

  if (preferOcbCipher) {
#if FOLLY_OPENSSL_IS_110 && !defined(OPENSSL_NO_OCB)
    auto ciphers = folly::copy(ctx->getSupportedCiphers());
    ciphers.insert(
        ciphers.begin(),
        fizz::CipherSuite::TLS_AES_128_OCB_SHA256_EXPERIMENTAL);
    ctx->setSupportedCiphers(std::move(ciphers));
#endif
  }

  return FizzContextAndVerifier(std::move(ctx), std::move(verifier));
}

std::shared_ptr<fizz::server::FizzServerContext> createFizzServerContext(
    folly::StringPiece pemCertPath,
    folly::StringPiece certData,
    folly::StringPiece pemKeyPath,
    folly::StringPiece keyData,
    folly::StringPiece pemCaPath,
    bool requireClientVerification,
    bool preferOcbCipher,
    wangle::TLSTicketKeySeeds* ticketKeySeeds) {
  initSSL();
  auto certMgr = std::make_unique<fizz::server::CertManager>();
  try {
    auto selfCert =
        fizz::CertUtils::makeSelfCert(certData.str(), keyData.str());
    // add the default cert
    certMgr->addCert(std::move(selfCert), true);
  } catch (const std::exception& ex) {
    LOG_FAILURE(
        "SSLCert",
        failure::Category::kBadEnvironment,
        "Failed to create self cert from \"{}\" and \"{}\".  ex: {}",
        pemCertPath,
        pemKeyPath,
        ex.what());
    return nullptr;
  }

  auto ctx = std::make_shared<fizz::server::FizzServerContext>();
  ctx->setSupportedVersions({fizz::ProtocolVersion::tls_1_3});
  ctx->setSupportedPskModes(
      {fizz::PskKeyExchangeMode::psk_ke, fizz::PskKeyExchangeMode::psk_dhe_ke});
  ctx->setVersionFallbackEnabled(true);
  ctx->setCertManager(std::move(certMgr));
  if (!pemCaPath.empty()) {
    auto verifier = fizz::DefaultCertificateVerifier::createFromCAFile(
        fizz::VerificationContext::Server, pemCaPath.str());
    ctx->setClientCertVerifier(std::move(verifier));
    ctx->setClientAuthMode(fizz::server::ClientAuthMode::Optional);
  }
  if (requireClientVerification) {
    ctx->setClientAuthMode(fizz::server::ClientAuthMode::Required);
  }
  if (preferOcbCipher) {
#if FOLLY_OPENSSL_IS_110 && !defined(OPENSSL_NO_OCB)
    auto serverCiphers = folly::copy(ctx->getSupportedCiphers());
    serverCiphers.insert(
        serverCiphers.begin(),
        {
            fizz::CipherSuite::TLS_AES_128_OCB_SHA256_EXPERIMENTAL,
        });
    ctx->setSupportedCiphers(std::move(serverCiphers));
#endif
  }

  // set ticket seeds
  if (ticketKeySeeds) {
    std::vector<folly::ByteRange> ticketSecrets;
    for (const auto& secret : ticketKeySeeds->currentSeeds) {
      ticketSecrets.push_back(folly::StringPiece(secret));
    }
    for (const auto& secret : ticketKeySeeds->oldSeeds) {
      ticketSecrets.push_back(folly::StringPiece(secret));
    }
    for (const auto& secret : ticketKeySeeds->newSeeds) {
      ticketSecrets.push_back(folly::StringPiece(secret));
    }
    auto cipher = std::make_shared<fizz::server::AES128TicketCipher>();
    cipher->setTicketSecrets(std::move(ticketSecrets));
    fizz::server::TicketPolicy policy;
    policy.setTicketValidity(std::chrono::seconds(kSessionLifeTime));
    policy.setHandshakeValidity(std::chrono::seconds(kHandshakeValidity));
    cipher->setPolicy(std::move(policy));
    ctx->setTicketCipher(std::move(cipher));
  }
  // TODO: allow for custom FizzFactory
  return ctx;
}
} // namespace memcache
} // namespace facebook
<|endoftext|>


<commit_before>#include <algorithm>

#include "EntityManager.h"
#include "EntityType.h"

#include "components/debug/Debug.h"

template <typename T>
int EntityManager::EntityGroup<T>::getCount() const
{
	return static_cast<int>(this->indices.size());
}

template <typename T>
T *EntityManager::EntityGroup<T>::getEntityAtIndex(int index)
{
	DebugAssert(this->validEntities.size() == this->entities.size());
	DebugAssertIndex(this->validEntities, index);
	const bool isValid = this->validEntities[index];
	return isValid ? &this->entities[index] : nullptr;
}

template <typename T>
const T *EntityManager::EntityGroup<T>::getEntityAtIndex(int index) const
{
	DebugAssert(this->validEntities.size() == this->entities.size());
	DebugAssertIndex(this->validEntities, index);
	const bool isValid = this->validEntities[index];
	return isValid ? &this->entities[index] : nullptr;
}

template <typename T>
int EntityManager::EntityGroup<T>::getEntities(Entity **outEntities, int outSize)
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);
	DebugAssert(this->validEntities.size() == this->entities.size());

	int writeIndex = 0;
	const int count = this->getCount();
	for (int i = 0; i < count; i++)
	{
		// Break if the destination buffer is full.
		if (writeIndex == outSize)
		{
			break;
		}

		DebugAssertIndex(this->validEntities, i);
		const bool isValid = this->validEntities[i];

		// Skip if entity is not valid.
		if (!isValid)
		{
			continue;
		}

		T &entity = this->entities[i];
		outEntities[writeIndex] = &entity;
		writeIndex++;
	}

	return writeIndex;
}

template <typename T>
int EntityManager::EntityGroup<T>::getEntities(const Entity **outEntities, int outSize) const
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);
	DebugAssert(this->validEntities.size() == this->entities.size());

	int writeIndex = 0;
	const int count = this->getCount();
	for (int i = 0; i < count; i++)
	{
		// Break if the destination buffer is full.
		if (writeIndex == outSize)
		{
			break;
		}

		DebugAssertIndex(this->validEntities, i);
		const bool isValid = this->validEntities[i];

		// Skip if entity is not valid.
		if (!isValid)
		{
			continue;
		}

		const T &entity = this->entities[i];
		outEntities[writeIndex] = &entity;
		writeIndex++;
	}

	return writeIndex;
}

template <typename T>
std::optional<int> EntityManager::EntityGroup<T>::getEntityIndex(int id) const
{
	const auto iter = this->indices.find(id);
	if (iter != this->indices.end())
	{
		return iter->second;
	}
	else
	{
		return std::nullopt;
	}
}

template <typename T>
T *EntityManager::EntityGroup<T>::addEntity(int id)
{
	DebugAssert(id != EntityManager::NO_ID);
	DebugAssert(this->validEntities.size() == this->entities.size());

	// Entity ID must not already be in use.
	DebugAssert(!this->getEntityIndex(id).has_value());

	// Find available position in entities array.
	int index;
	if (this->freeIndices.size() > 0)
	{
		// Reuse a previously-owned entity slot.
		index = this->freeIndices.back();
		this->freeIndices.pop_back();

		DebugAssertIndex(this->validEntities, index);
		this->validEntities[index] = true;
	}
	else
	{
		// Insert new at the end of the entities list.
		index = static_cast<int>(this->entities.size());
		this->entities.push_back(T());
		this->validEntities.push_back(true);
	}

	// Initialize basic entity data.
	DebugAssertIndex(this->entities, index);
	T &entitySlot = this->entities[index];
	entitySlot.reset();
	entitySlot.setID(id);

	// Insert into ID -> entity index table.
	this->indices.insert(std::make_pair(id, index));

	return &entitySlot;
}

template <typename T>
void EntityManager::EntityGroup<T>::remove(int id)
{
	DebugAssert(id != EntityManager::NO_ID);
	DebugAssert(this->validEntities.size() == this->entities.size());

	// Find entity with the given ID.
	const std::optional<int> optIndex = this->getEntityIndex(id);
	if (optIndex.has_value())
	{
		const int index = optIndex.value();

		// Clear entity slot.
		DebugAssertIndex(this->entities, index);
		this->entities[index].reset();
		this->validEntities[index] = false;

		// Clear ID mapping.
		this->indices.erase(id);

		// Add ID to previously-owned IDs list.
		this->freeIndices.push_back(id);
	}
	else
	{
		// Not in entity group.
		DebugLogWarning("Tried to remove missing entity \"" + std::to_string(id) + "\".");
	}
}

template <typename T>
void EntityManager::EntityGroup<T>::clear()
{
	this->entities.clear();
	this->validEntities.clear();
	this->indices.clear();
	this->freeIndices.clear();
}

const int EntityManager::NO_ID = -1;

EntityManager::EntityManager()
{
	this->nextID = 0;
}

int EntityManager::nextFreeID()
{
	// Check if any pre-owned entity IDs are available.
	if (this->freeIDs.size() > 0)
	{
		const int id = this->freeIDs.back();
		this->freeIDs.pop_back();
		return id;
	}
	else
	{
		// Get the next available ID.
		const int id = this->nextID;
		this->nextID++;
		return id;
	}
}

Doodad *EntityManager::makeDoodad()
{
	const int id = this->nextFreeID();
	Doodad *doodad = this->doodads.addEntity(id);
	DebugAssert(doodad->getID() == id);
	return doodad;
}

NonPlayer *EntityManager::makeNPC()
{
	const int id = this->nextFreeID();
	NonPlayer *npc = this->npcs.addEntity(id);
	DebugAssert(npc->getID() == id);
	return npc;
}

Entity *EntityManager::get(int id)
{
	// Find which entity group the given ID is in.
	std::optional<int> entityIndex = this->npcs.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// NPC.
		return this->npcs.getEntityAtIndex(entityIndex.value());
	}

	entityIndex = this->doodads.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// Doodad.
		return this->doodads.getEntityAtIndex(entityIndex.value());
	}

	// Not in any entity group.
	return nullptr;
}

const Entity *EntityManager::get(int id) const
{
	// Find which entity group the given ID is in.
	std::optional<int> entityIndex = this->npcs.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// NPC.
		return this->npcs.getEntityAtIndex(entityIndex.value());
	}

	entityIndex = this->doodads.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// Doodad.
		return this->doodads.getEntityAtIndex(entityIndex.value());
	}

	// Not in any entity group.
	return nullptr;
}

int EntityManager::getCount(EntityType entityType) const
{
	switch (entityType)
	{
	case EntityType::NonPlayer:
		return this->npcs.getCount();
	case EntityType::Doodad:
		return this->doodads.getCount();
	default:
		DebugUnhandledReturnMsg(int, std::to_string(static_cast<int>(entityType)));
	}
}

int EntityManager::getTotalCount() const
{
	return this->npcs.getCount() + this->doodads.getCount();
}

int EntityManager::getEntities(EntityType entityType, Entity **outEntities, int outSize)
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);

	// Get entities from the desired type.
	switch (entityType)
	{
	case EntityType::NonPlayer:
		return this->npcs.getEntities(outEntities, outSize);
	case EntityType::Doodad:
		return this->doodads.getEntities(outEntities, outSize);
	default:
		DebugUnhandledReturnMsg(int, std::to_string(static_cast<int>(entityType)));
	}
}

int EntityManager::getEntities(EntityType entityType, const Entity **outEntities, int outSize) const
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);

	// Get entities from the desired type.
	switch (entityType)
	{
	case EntityType::NonPlayer:
		return this->npcs.getEntities(outEntities, outSize);
	case EntityType::Doodad:
		return this->doodads.getEntities(outEntities, outSize);
	default:
		DebugUnhandledReturnMsg(int, std::to_string(static_cast<int>(entityType)));
	}
}

int EntityManager::getTotalEntities(const Entity **outEntities, int outSize) const
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);

	// Fill the output buffer with as many entities as will fit.
	int writeIndex = 0;
	auto tryWriteEntities = [outEntities, outSize, &writeIndex](const auto &entityGroup)
	{
		const int entityCount = entityGroup.getCount();

		for (int i = 0; i < entityCount; i++)
		{
			// Break if the output buffer is full.
			if (writeIndex == outSize)
			{
				break;
			}

			outEntities[writeIndex] = entityGroup.getEntityAtIndex(i);
			writeIndex++;
		}
	};

	tryWriteEntities(this->npcs);
	tryWriteEntities(this->doodads);

	return writeIndex;
}

void EntityManager::remove(int id)
{
	// Find which entity group the given ID is in.
	std::optional<int> entityIndex = this->npcs.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// NPC.
		this->npcs.remove(id);

		// Insert entity ID into the free list.
		this->freeIDs.push_back(id);
		return;
	}

	entityIndex = this->doodads.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// Doodad.
		this->doodads.remove(id);

		// Insert entity ID into the free list.
		this->freeIDs.push_back(id);
		return;
	}

	// Not in any entity group.
	DebugLogWarning("Tried to remove missing entity \"" + std::to_string(id) + "\".");
}

void EntityManager::clear()
{
	this->npcs.clear();
	this->doodads.clear();

	this->freeIDs.clear();
	this->nextID = 0;
}
<commit_msg>Fixed index value given to freeIndices list.<commit_after>#include <algorithm>

#include "EntityManager.h"
#include "EntityType.h"

#include "components/debug/Debug.h"

template <typename T>
int EntityManager::EntityGroup<T>::getCount() const
{
	return static_cast<int>(this->indices.size());
}

template <typename T>
T *EntityManager::EntityGroup<T>::getEntityAtIndex(int index)
{
	DebugAssert(this->validEntities.size() == this->entities.size());
	DebugAssertIndex(this->validEntities, index);
	const bool isValid = this->validEntities[index];
	return isValid ? &this->entities[index] : nullptr;
}

template <typename T>
const T *EntityManager::EntityGroup<T>::getEntityAtIndex(int index) const
{
	DebugAssert(this->validEntities.size() == this->entities.size());
	DebugAssertIndex(this->validEntities, index);
	const bool isValid = this->validEntities[index];
	return isValid ? &this->entities[index] : nullptr;
}

template <typename T>
int EntityManager::EntityGroup<T>::getEntities(Entity **outEntities, int outSize)
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);
	DebugAssert(this->validEntities.size() == this->entities.size());

	int writeIndex = 0;
	const int count = this->getCount();
	for (int i = 0; i < count; i++)
	{
		// Break if the destination buffer is full.
		if (writeIndex == outSize)
		{
			break;
		}

		DebugAssertIndex(this->validEntities, i);
		const bool isValid = this->validEntities[i];

		// Skip if entity is not valid.
		if (!isValid)
		{
			continue;
		}

		T &entity = this->entities[i];
		outEntities[writeIndex] = &entity;
		writeIndex++;
	}

	return writeIndex;
}

template <typename T>
int EntityManager::EntityGroup<T>::getEntities(const Entity **outEntities, int outSize) const
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);
	DebugAssert(this->validEntities.size() == this->entities.size());

	int writeIndex = 0;
	const int count = this->getCount();
	for (int i = 0; i < count; i++)
	{
		// Break if the destination buffer is full.
		if (writeIndex == outSize)
		{
			break;
		}

		DebugAssertIndex(this->validEntities, i);
		const bool isValid = this->validEntities[i];

		// Skip if entity is not valid.
		if (!isValid)
		{
			continue;
		}

		const T &entity = this->entities[i];
		outEntities[writeIndex] = &entity;
		writeIndex++;
	}

	return writeIndex;
}

template <typename T>
std::optional<int> EntityManager::EntityGroup<T>::getEntityIndex(int id) const
{
	const auto iter = this->indices.find(id);
	if (iter != this->indices.end())
	{
		return iter->second;
	}
	else
	{
		return std::nullopt;
	}
}

template <typename T>
T *EntityManager::EntityGroup<T>::addEntity(int id)
{
	DebugAssert(id != EntityManager::NO_ID);
	DebugAssert(this->validEntities.size() == this->entities.size());

	// Entity ID must not already be in use.
	DebugAssert(!this->getEntityIndex(id).has_value());

	// Find available position in entities array.
	int index;
	if (this->freeIndices.size() > 0)
	{
		// Reuse a previously-owned entity slot.
		index = this->freeIndices.back();
		this->freeIndices.pop_back();

		DebugAssertIndex(this->validEntities, index);
		this->validEntities[index] = true;
	}
	else
	{
		// Insert new at the end of the entities list.
		index = static_cast<int>(this->entities.size());
		this->entities.push_back(T());
		this->validEntities.push_back(true);
	}

	// Initialize basic entity data.
	DebugAssertIndex(this->entities, index);
	T &entitySlot = this->entities[index];
	entitySlot.reset();
	entitySlot.setID(id);

	// Insert into ID -> entity index table.
	this->indices.insert(std::make_pair(id, index));

	return &entitySlot;
}

template <typename T>
void EntityManager::EntityGroup<T>::remove(int id)
{
	DebugAssert(id != EntityManager::NO_ID);
	DebugAssert(this->validEntities.size() == this->entities.size());

	// Find entity with the given ID.
	const std::optional<int> optIndex = this->getEntityIndex(id);
	if (optIndex.has_value())
	{
		const int index = optIndex.value();

		// Clear entity slot.
		DebugAssertIndex(this->entities, index);
		this->entities[index].reset();
		this->validEntities[index] = false;

		// Clear ID mapping.
		this->indices.erase(id);

		// Add entity index to previously-owned slots list.
		this->freeIndices.push_back(index);
	}
	else
	{
		// Not in entity group.
		DebugLogWarning("Tried to remove missing entity \"" + std::to_string(id) + "\".");
	}
}

template <typename T>
void EntityManager::EntityGroup<T>::clear()
{
	this->entities.clear();
	this->validEntities.clear();
	this->indices.clear();
	this->freeIndices.clear();
}

const int EntityManager::NO_ID = -1;

EntityManager::EntityManager()
{
	this->nextID = 0;
}

int EntityManager::nextFreeID()
{
	// Check if any pre-owned entity IDs are available.
	if (this->freeIDs.size() > 0)
	{
		const int id = this->freeIDs.back();
		this->freeIDs.pop_back();
		return id;
	}
	else
	{
		// Get the next available ID.
		const int id = this->nextID;
		this->nextID++;
		return id;
	}
}

Doodad *EntityManager::makeDoodad()
{
	const int id = this->nextFreeID();
	Doodad *doodad = this->doodads.addEntity(id);
	DebugAssert(doodad->getID() == id);
	return doodad;
}

NonPlayer *EntityManager::makeNPC()
{
	const int id = this->nextFreeID();
	NonPlayer *npc = this->npcs.addEntity(id);
	DebugAssert(npc->getID() == id);
	return npc;
}

Entity *EntityManager::get(int id)
{
	// Find which entity group the given ID is in.
	std::optional<int> entityIndex = this->npcs.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// NPC.
		return this->npcs.getEntityAtIndex(entityIndex.value());
	}

	entityIndex = this->doodads.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// Doodad.
		return this->doodads.getEntityAtIndex(entityIndex.value());
	}

	// Not in any entity group.
	return nullptr;
}

const Entity *EntityManager::get(int id) const
{
	// Find which entity group the given ID is in.
	std::optional<int> entityIndex = this->npcs.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// NPC.
		return this->npcs.getEntityAtIndex(entityIndex.value());
	}

	entityIndex = this->doodads.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// Doodad.
		return this->doodads.getEntityAtIndex(entityIndex.value());
	}

	// Not in any entity group.
	return nullptr;
}

int EntityManager::getCount(EntityType entityType) const
{
	switch (entityType)
	{
	case EntityType::NonPlayer:
		return this->npcs.getCount();
	case EntityType::Doodad:
		return this->doodads.getCount();
	default:
		DebugUnhandledReturnMsg(int, std::to_string(static_cast<int>(entityType)));
	}
}

int EntityManager::getTotalCount() const
{
	return this->npcs.getCount() + this->doodads.getCount();
}

int EntityManager::getEntities(EntityType entityType, Entity **outEntities, int outSize)
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);

	// Get entities from the desired type.
	switch (entityType)
	{
	case EntityType::NonPlayer:
		return this->npcs.getEntities(outEntities, outSize);
	case EntityType::Doodad:
		return this->doodads.getEntities(outEntities, outSize);
	default:
		DebugUnhandledReturnMsg(int, std::to_string(static_cast<int>(entityType)));
	}
}

int EntityManager::getEntities(EntityType entityType, const Entity **outEntities, int outSize) const
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);

	// Get entities from the desired type.
	switch (entityType)
	{
	case EntityType::NonPlayer:
		return this->npcs.getEntities(outEntities, outSize);
	case EntityType::Doodad:
		return this->doodads.getEntities(outEntities, outSize);
	default:
		DebugUnhandledReturnMsg(int, std::to_string(static_cast<int>(entityType)));
	}
}

int EntityManager::getTotalEntities(const Entity **outEntities, int outSize) const
{
	DebugAssert(outEntities != nullptr);
	DebugAssert(outSize >= 0);

	// Fill the output buffer with as many entities as will fit.
	int writeIndex = 0;
	auto tryWriteEntities = [outEntities, outSize, &writeIndex](const auto &entityGroup)
	{
		const int entityCount = entityGroup.getCount();

		for (int i = 0; i < entityCount; i++)
		{
			// Break if the output buffer is full.
			if (writeIndex == outSize)
			{
				break;
			}

			outEntities[writeIndex] = entityGroup.getEntityAtIndex(i);
			writeIndex++;
		}
	};

	tryWriteEntities(this->npcs);
	tryWriteEntities(this->doodads);

	return writeIndex;
}

void EntityManager::remove(int id)
{
	// Find which entity group the given ID is in.
	std::optional<int> entityIndex = this->npcs.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// NPC.
		this->npcs.remove(id);

		// Insert entity ID into the free list.
		this->freeIDs.push_back(id);
		return;
	}

	entityIndex = this->doodads.getEntityIndex(id);
	if (entityIndex.has_value())
	{
		// Doodad.
		this->doodads.remove(id);

		// Insert entity ID into the free list.
		this->freeIDs.push_back(id);
		return;
	}

	// Not in any entity group.
	DebugLogWarning("Tried to remove missing entity \"" + std::to_string(id) + "\".");
}

void EntityManager::clear()
{
	this->npcs.clear();
	this->doodads.clear();

	this->freeIDs.clear();
	this->nextID = 0;
}
<|endoftext|>


<commit_before>#include "oddlib/path.hpp"
#include "oddlib/stream.hpp"
#include "logger.hpp"
#include <array>

namespace Oddlib
{
    void Path::Point16::Read(IStream& stream)
    {
        stream.Read(mX);
        stream.Read(mY);
    }

    void Path::Links::Read(IStream& stream)
    {
        stream.Read(mPrevious);
        stream.Read(mNext);
    }

    void Path::CollisionItem::Read(IStream& stream)
    {
        mP1.Read(stream);
        mP2.Read(stream);
        stream.Read(mType);
        mLinks[0].Read(stream);
        mLinks[1].Read(stream);
        stream.Read(mLineLength);
    }

    Path::Path( IStream& pathChunkStream,
                u32 collisionDataOffset,
                u32 objectIndexTableOffset,
                u32 objectDataOffset,
                u32 mapXSize, u32 mapYSize,
                bool isAo)
     : mXSize(mapXSize), mYSize(mapYSize), mIsAo(isAo)
    {
        TRACE_ENTRYEXIT;
        ReadCameraMap(pathChunkStream);

        if (collisionDataOffset != 0)
        {
            //pathChunkStream.BinaryDump("PATH.DUMP");

            assert(pathChunkStream.Pos()+16 == collisionDataOffset);
        }

        // TODO: Psx data != pc data for Ao
        const u32 indexTableOffset = (pathChunkStream.Size() - (mCameras.size() * sizeof(u32))) + 16;
        assert(indexTableOffset == objectIndexTableOffset);

        if (collisionDataOffset != 0)
        {
            const u32 numCollisionDataBytes = objectDataOffset - collisionDataOffset;
            const u32 numCollisionItems = numCollisionDataBytes / kCollisionItemSize;
            ReadCollisionItems(pathChunkStream, numCollisionItems);
            ReadMapObjects(pathChunkStream, objectIndexTableOffset);
        }
    }

    u32 Path::XSize() const
    {
        return mXSize;
    }

    u32 Path::YSize() const
    {
        return mYSize;
    }

    const Path::Camera& Path::CameraByPosition(u32 x, u32 y) const
    {
        if (x >= XSize() || y >= YSize())
        {
            LOG_ERROR("Out of bounds x:y"
                << std::to_string(x) << " " << std::to_string(y) <<" vs "
                << std::to_string(XSize()) << " " << std::to_string(YSize()));
        }

        return mCameras[(y * XSize()) + x];
    }

    void Path::ReadCameraMap(IStream& stream)
    {
        const u32 numberOfCameras = XSize() * YSize();
        mCameras.reserve(numberOfCameras);

        std::array<u8, 8> nameBuffer;
        for (u32 i = 0; i < numberOfCameras; i++)
        {
            stream.Read(nameBuffer);
            std::string tmpStr(reinterpret_cast<const char*>(nameBuffer.data()), nameBuffer.size());
            if (tmpStr[0] != 0)
            {
                tmpStr += ".CAM";
            }
            mCameras.emplace_back(Camera(std::move(tmpStr)));
        }
    }

    void Path::ReadCollisionItems(IStream& stream, u32 numberOfCollisionItems)
    {
        mCollisionItems.resize(numberOfCollisionItems);
        for (u32 i = 0; i < numberOfCollisionItems; i++)
        {
            mCollisionItems[i].Read(stream);
        }
    }

    void Path::ReadMapObjects(IStream& stream, u32 objectIndexTableOffset)
    {
        const size_t collisionEnd = stream.Pos();

        // TODO -16 is for the chunk header, probably shouldn't have this already included in the
        // pathdb, may also apply to collision info
        stream.Seek(objectIndexTableOffset-16);

        // Read the pointers to the object list for each camera
        const u32 numberOfCameras = XSize() * YSize();
        std::vector<u32> cameraObjectOffsets;
        cameraObjectOffsets.reserve(numberOfCameras);
        for (u32 i = 0; i < numberOfCameras; i++)
        {
            u32 offset = 0;
            stream.Read(offset);
            cameraObjectOffsets.push_back(offset);
        }

        // Now load the objects for each camera
        for (auto i = 0u; i < cameraObjectOffsets.size(); i++)
        {
            // If max u32/-1 then it means there are no objects for this camera
            const auto objectsOffset = cameraObjectOffsets[i];
            if (objectsOffset != 0xFFFFFFFF)
            {
                stream.Seek(collisionEnd + objectsOffset);
                for (;;)
                {
                    MapObject mapObject;
                    stream.Read(mapObject.mFlags);
                    stream.Read(mapObject.mLength);
                    stream.Read(mapObject.mType);

                    LOG_INFO("Object TLV: " << mapObject.mType << " " << mapObject.mLength << " " << mapObject.mLength);

                    if (mIsAo)
                    {
                        // Don't know what this is for
                        u32 unknownData = 0;
                        stream.Read(unknownData);
                    }

                    stream.Read(mapObject.mRectTopLeft.mX);
                    stream.Read(mapObject.mRectTopLeft.mY);

                    // Ao duplicated the first two parts of data for some reason
                    if (mIsAo)
                    {
                        u32 duplicatedXY = 0;
                        stream.Read(duplicatedXY);
                    }

                    stream.Read(mapObject.mRectBottomRight.mX);
                    stream.Read(mapObject.mRectBottomRight.mY);

                    if (mapObject.mLength > 0)
                    {
                        const u32 len = mapObject.mLength - (sizeof(u16) * (mIsAo ? 12 : 8));
                        if (len > 512)
                        {
                            LOG_ERROR("Map object data length " << mapObject.mLength << " is larger than fixed size");
                            abort();
                        }
                        stream.ReadBytes(mapObject.mData.data(), len);
                    }

                    mCameras[i].mObjects.emplace_back(mapObject);

                    if (mapObject.mFlags & 0x4)
                    {
                        break;
                    }
                }
            }
        }
    }
}<commit_msg>temp warning fix<commit_after>#include "oddlib/path.hpp"
#include "oddlib/stream.hpp"
#include "logger.hpp"
#include <array>

namespace Oddlib
{
    void Path::Point16::Read(IStream& stream)
    {
        stream.Read(mX);
        stream.Read(mY);
    }

    void Path::Links::Read(IStream& stream)
    {
        stream.Read(mPrevious);
        stream.Read(mNext);
    }

    void Path::CollisionItem::Read(IStream& stream)
    {
        mP1.Read(stream);
        mP2.Read(stream);
        stream.Read(mType);
        mLinks[0].Read(stream);
        mLinks[1].Read(stream);
        stream.Read(mLineLength);
    }

    Path::Path( IStream& pathChunkStream,
                u32 collisionDataOffset,
                u32 objectIndexTableOffset,
                u32 objectDataOffset,
                u32 mapXSize, u32 mapYSize,
                bool isAo)
     : mXSize(mapXSize), mYSize(mapYSize), mIsAo(isAo)
    {
        TRACE_ENTRYEXIT;
        ReadCameraMap(pathChunkStream);

        if (collisionDataOffset != 0)
        {
            //pathChunkStream.BinaryDump("PATH.DUMP");

            assert(pathChunkStream.Pos()+16 == collisionDataOffset);
        }

        // TODO: Psx data != pc data for Ao
        //const u32 indexTableOffset = (pathChunkStream.Size() - (mCameras.size() * sizeof(u32))) + 16;
        //assert(indexTableOffset == objectIndexTableOffset);

        if (collisionDataOffset != 0)
        {
            const u32 numCollisionDataBytes = objectDataOffset - collisionDataOffset;
            const u32 numCollisionItems = numCollisionDataBytes / kCollisionItemSize;
            ReadCollisionItems(pathChunkStream, numCollisionItems);
            ReadMapObjects(pathChunkStream, objectIndexTableOffset);
        }
    }

    u32 Path::XSize() const
    {
        return mXSize;
    }

    u32 Path::YSize() const
    {
        return mYSize;
    }

    const Path::Camera& Path::CameraByPosition(u32 x, u32 y) const
    {
        if (x >= XSize() || y >= YSize())
        {
            LOG_ERROR("Out of bounds x:y"
                << std::to_string(x) << " " << std::to_string(y) <<" vs "
                << std::to_string(XSize()) << " " << std::to_string(YSize()));
        }

        return mCameras[(y * XSize()) + x];
    }

    void Path::ReadCameraMap(IStream& stream)
    {
        const u32 numberOfCameras = XSize() * YSize();
        mCameras.reserve(numberOfCameras);

        std::array<u8, 8> nameBuffer;
        for (u32 i = 0; i < numberOfCameras; i++)
        {
            stream.Read(nameBuffer);
            std::string tmpStr(reinterpret_cast<const char*>(nameBuffer.data()), nameBuffer.size());
            if (tmpStr[0] != 0)
            {
                tmpStr += ".CAM";
            }
            mCameras.emplace_back(Camera(std::move(tmpStr)));
        }
    }

    void Path::ReadCollisionItems(IStream& stream, u32 numberOfCollisionItems)
    {
        mCollisionItems.resize(numberOfCollisionItems);
        for (u32 i = 0; i < numberOfCollisionItems; i++)
        {
            mCollisionItems[i].Read(stream);
        }
    }

    void Path::ReadMapObjects(IStream& stream, u32 objectIndexTableOffset)
    {
        const size_t collisionEnd = stream.Pos();

        // TODO -16 is for the chunk header, probably shouldn't have this already included in the
        // pathdb, may also apply to collision info
        stream.Seek(objectIndexTableOffset-16);

        // Read the pointers to the object list for each camera
        const u32 numberOfCameras = XSize() * YSize();
        std::vector<u32> cameraObjectOffsets;
        cameraObjectOffsets.reserve(numberOfCameras);
        for (u32 i = 0; i < numberOfCameras; i++)
        {
            u32 offset = 0;
            stream.Read(offset);
            cameraObjectOffsets.push_back(offset);
        }

        // Now load the objects for each camera
        for (auto i = 0u; i < cameraObjectOffsets.size(); i++)
        {
            // If max u32/-1 then it means there are no objects for this camera
            const auto objectsOffset = cameraObjectOffsets[i];
            if (objectsOffset != 0xFFFFFFFF)
            {
                stream.Seek(collisionEnd + objectsOffset);
                for (;;)
                {
                    MapObject mapObject;
                    stream.Read(mapObject.mFlags);
                    stream.Read(mapObject.mLength);
                    stream.Read(mapObject.mType);

                    LOG_INFO("Object TLV: " << mapObject.mType << " " << mapObject.mLength << " " << mapObject.mLength);

                    if (mIsAo)
                    {
                        // Don't know what this is for
                        u32 unknownData = 0;
                        stream.Read(unknownData);
                    }

                    stream.Read(mapObject.mRectTopLeft.mX);
                    stream.Read(mapObject.mRectTopLeft.mY);

                    // Ao duplicated the first two parts of data for some reason
                    if (mIsAo)
                    {
                        u32 duplicatedXY = 0;
                        stream.Read(duplicatedXY);
                    }

                    stream.Read(mapObject.mRectBottomRight.mX);
                    stream.Read(mapObject.mRectBottomRight.mY);

                    if (mapObject.mLength > 0)
                    {
                        const u32 len = mapObject.mLength - (sizeof(u16) * (mIsAo ? 12 : 8));
                        if (len > 512)
                        {
                            LOG_ERROR("Map object data length " << mapObject.mLength << " is larger than fixed size");
                            abort();
                        }
                        stream.ReadBytes(mapObject.mData.data(), len);
                    }

                    mCameras[i].mObjects.emplace_back(mapObject);

                    if (mapObject.mFlags & 0x4)
                    {
                        break;
                    }
                }
            }
        }
    }
}<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// root
#include <TROOT.h>
#include <TSystem.h>
#include <TInterpreter.h>
#include <TChain.h>
#include <TFile.h>
#include <Riostream.h>

// analysis
#include "AliAnalysisTaskParticleCorrelation.h"
#include "AliAnalysisManager.h"
#include "AliESDInputHandler.h"
#include "AliMCEventHandler.h"
#include "AliMCEvent.h"
#include "AliAnaMaker.h"
#include "AliCaloTrackReader.h"
#include "AliESDEvent.h"
#include "AliAODEvent.h"
#include "AliAODHandler.h"
#include "AliStack.h"
#include "AliLog.h"

ClassImp(AliAnalysisTaskParticleCorrelation)

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

  AliAnalysisTaskParticleCorrelation::AliAnalysisTaskParticleCorrelation():
    AliAnalysisTaskSE(),
    fAna(0x0),
    fOutputContainer(0x0),
    fAODBranch(0x0),
    fConfigName(0)
{
  // Default constructor
}

//_____________________________________________________
AliAnalysisTaskParticleCorrelation::AliAnalysisTaskParticleCorrelation(const char* name):
    AliAnalysisTaskSE(name),
    fAna(0x0),
    fOutputContainer(0x0),
    fAODBranch(0x0),
    fConfigName("ConfigAnalysis")
{
  // Default constructor

  DefineOutput(1, TList::Class());

}

//_____________________________________________________
AliAnalysisTaskParticleCorrelation::~AliAnalysisTaskParticleCorrelation()
{
  // Remove all pointers

  if(fOutputContainer){
    fOutputContainer->Clear() ;
    delete fOutputContainer ;
  }

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::UserCreateOutputObjects()
{
  // Create the output container
  if (fDebug > 1) printf("AnalysisTaskParticleCorrelation::CreateOutputData() \n");

  //AODs
  fAODBranch = new TClonesArray("AliAODParticleCorrelation", 0);
  fAODBranch->SetName(fAna->GetAODBranchName());
  AddAODBranch("TClonesArray", fAODBranch);
  fAna->SetAODBranch(fAODBranch);

  //Histograms container
  OpenFile(1);
  fOutputContainer = fAna->GetOutputContainer();

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::Init()
{
  // Initialization
  if (fDebug > 1) printf("AnalysisTaskParticleCorrelation::Init() \n");

  // Call configuration file

  if(fConfigName == ""){
    fConfigName="ConfigAnalysis";
  }

  AliInfo(Form("### Configuration file is %s.C ###", fConfigName.Data()));
  gROOT->LoadMacro(fConfigName+".C");
  fAna = (AliAnaMaker*) gInterpreter->ProcessLine("ConfigAnalysis()");

  if(!fAna)
    AliFatal("Analysis pointer not initialized, abort analysis!");

  // Initialise analysis
  fAna->Init();

  AliDebug(1,"End");

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::UserExec(Option_t */*option*/)
{
  // Execute analysis for current event
  //
  if (fDebug > 1) printf("AnalysisTaskParticleCorrelation::Exec() \n");

  //Get the type of data, check if type is correct
  Int_t  datatype = fAna->GetReader()->GetDataType();
  if(datatype != AliCaloTrackReader::kESD && datatype != AliCaloTrackReader::kAOD &&
     datatype != AliCaloTrackReader::kMC){
    AliFatal("Wrong type of data");
    return ;
  }

  fAna->GetReader()->SetInputEvent(InputEvent(), AODEvent(), MCEvent());

  //Process event
  fAna->ProcessEvent((Int_t) Entry());

  PostData(1, fOutputContainer);

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::Terminate(Option_t */*option*/)
{
  // Terminate analysis
  //
  AliDebug(1,"Do nothing in Terminate");
  //fAna->Terminate();
}

<commit_msg>provide adress of the pointer to new AOD branch, not the pointer itself Mihaela G.<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

// root
#include <TROOT.h>
#include <TSystem.h>
#include <TInterpreter.h>
#include <TChain.h>
#include <TFile.h>
#include <Riostream.h>

// analysis
#include "AliAnalysisTaskParticleCorrelation.h"
#include "AliAnalysisManager.h"
#include "AliESDInputHandler.h"
#include "AliMCEventHandler.h"
#include "AliMCEvent.h"
#include "AliAnaMaker.h"
#include "AliCaloTrackReader.h"
#include "AliESDEvent.h"
#include "AliAODEvent.h"
#include "AliAODHandler.h"
#include "AliStack.h"
#include "AliLog.h"

ClassImp(AliAnalysisTaskParticleCorrelation)

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

  AliAnalysisTaskParticleCorrelation::AliAnalysisTaskParticleCorrelation():
    AliAnalysisTaskSE(),
    fAna(0x0),
    fOutputContainer(0x0),
    fAODBranch(0x0),
    fConfigName(0)
{
  // Default constructor
}

//_____________________________________________________
AliAnalysisTaskParticleCorrelation::AliAnalysisTaskParticleCorrelation(const char* name):
    AliAnalysisTaskSE(name),
    fAna(0x0),
    fOutputContainer(0x0),
    fAODBranch(0x0),
    fConfigName("ConfigAnalysis")
{
  // Default constructor

  DefineOutput(1, TList::Class());

}

//_____________________________________________________
AliAnalysisTaskParticleCorrelation::~AliAnalysisTaskParticleCorrelation()
{
  // Remove all pointers

  if(fOutputContainer){
    fOutputContainer->Clear() ;
    delete fOutputContainer ;
  }

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::UserCreateOutputObjects()
{
  // Create the output container
  if (fDebug > 1) printf("AnalysisTaskParticleCorrelation::CreateOutputData() \n");

  //AODs
  fAODBranch = new TClonesArray("AliAODParticleCorrelation", 0);
  fAODBranch->SetName(fAna->GetAODBranchName());
  AddAODBranch("TClonesArray", &fAODBranch);
  fAna->SetAODBranch(fAODBranch);

  //Histograms container
  OpenFile(1);
  fOutputContainer = fAna->GetOutputContainer();

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::Init()
{
  // Initialization
  if (fDebug > 1) printf("AnalysisTaskParticleCorrelation::Init() \n");

  // Call configuration file

  if(fConfigName == ""){
    fConfigName="ConfigAnalysis";
  }

  AliInfo(Form("### Configuration file is %s.C ###", fConfigName.Data()));
  gROOT->LoadMacro(fConfigName+".C");
  fAna = (AliAnaMaker*) gInterpreter->ProcessLine("ConfigAnalysis()");

  if(!fAna)
    AliFatal("Analysis pointer not initialized, abort analysis!");

  // Initialise analysis
  fAna->Init();

  AliDebug(1,"End");

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::UserExec(Option_t */*option*/)
{
  // Execute analysis for current event
  //
  if (fDebug > 1) printf("AnalysisTaskParticleCorrelation::Exec() \n");

  //Get the type of data, check if type is correct
  Int_t  datatype = fAna->GetReader()->GetDataType();
  if(datatype != AliCaloTrackReader::kESD && datatype != AliCaloTrackReader::kAOD &&
     datatype != AliCaloTrackReader::kMC){
    AliFatal("Wrong type of data");
    return ;
  }

  fAna->GetReader()->SetInputEvent(InputEvent(), AODEvent(), MCEvent());

  //Process event
  fAna->ProcessEvent((Int_t) Entry());

  PostData(1, fOutputContainer);

}

//_____________________________________________________
void AliAnalysisTaskParticleCorrelation::Terminate(Option_t */*option*/)
{
  // Terminate analysis
  //
  AliDebug(1,"Do nothing in Terminate");
  //fAna->Terminate();
}

<|endoftext|>


<commit_before>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include "src/operators/pm.h"

#include <string.h>

#include <string>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <vector>
#include <list>
#include <memory>

#include "src/operators/operator.h"
#include "src/utils/acmp.h"
#include "src/utils/string.h"

namespace modsecurity {
namespace operators {

Pm::~Pm() {
    acmp_node_t *root = m_p->root_node;
    acmp_node_t *node = root;

    cleanup(root);

    free(m_p);
    m_p = NULL;
#ifdef MODSEC_MUTEX_ON_PM
    pthread_mutex_destroy(&m_lock);
#endif
}

void Pm::cleanup(acmp_node_t *n) {
    if (n == NULL) {
        return;
    }

    cleanup(n->sibling);
    cleanup(n->child);

    postOrderTraversal(n->btree);

    if (n->text && strlen(n->text) > 0) {
        free(n->text);
        n->text = NULL;
    }

    if (n->pattern && strlen(n->pattern) > 0) {
        free(n->pattern);
        n->pattern = NULL;
    }

    free(n);
}

void Pm::postOrderTraversal(acmp_btree_node_t *node) {
    if (node == NULL) {
        return;
    }

    postOrderTraversal(node->right);
    postOrderTraversal(node->left);

    free(node);
}

bool Pm::evaluate(Transaction *transaction, Rule *rule,
    const std::string &input, std::shared_ptr<RuleMessage> ruleMessage) {
    int rc = -1;
    ACMPT pt;
    pt.parser = m_p;
    pt.ptr = NULL;
    const char *match = NULL;
#ifdef MODSEC_MUTEX_ON_PM
    pthread_mutex_lock(&m_lock);
#endif
    rc = acmp_process_quick(&pt, &match, input.c_str(), input.length());
#ifdef MODSEC_MUTEX_ON_PM
    pthread_mutex_unlock(&m_lock);
#endif

    if (rc >= 0 && transaction) {
        std::string match_(match);
        logOffset(ruleMessage, rc - match_.size() + 1, match_.size());
        transaction->m_matched.push_back(match_);
    }

    if (rule && rule->m_containsCaptureAction && transaction && rc) {
        transaction->m_collections.m_tx_collection->storeOrUpdateFirst("0",
            std::string(match));
        ms_dbg_a(transaction, 7, "Added pm match TX.0: " + \
            std::string(match));
    }

    return rc >= 0;
}

bool Pm::init(const std::string &file, std::string *error) {
    std::vector<std::string> vec;
    std::istringstream *iss;
    const char *err = NULL;

#ifdef MODSEC_MUTEX_ON_PM
    pthread_mutex_init(&m_lock, NULL);
#endif
    char *content = parse_pm_content(m_param.c_str(), m_param.length(), &err);
    if (content == NULL) {
        iss = new std::istringstream(m_param);
    } else {
        iss = new std::istringstream(content);
    }

    std::copy(std::istream_iterator<std::string>(*iss),
        std::istream_iterator<std::string>(),
        back_inserter(vec));

    for (auto &a : vec) {
        acmp_add_pattern(m_p, a.c_str(), NULL, NULL, a.length());
    }

    while (m_p->is_failtree_done == 0) {
        acmp_prepare(m_p);
    }

    if (content) {
        free(content);
        content = NULL;
    }

    delete iss;

    return true;
}

}  // namespace operators
}  // namespace modsecurity
<commit_msg>Avoid using NULL string (match) in Pm::evaluate<commit_after>/*
 * ModSecurity, http://www.modsecurity.org/
 * Copyright (c) 2015 Trustwave Holdings, Inc. (http://www.trustwave.com/)
 *
 * You may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * If any of the files related to licensing are missing or if you have any
 * other questions related to licensing please contact Trustwave Holdings, Inc.
 * directly using the email address security@modsecurity.org.
 *
 */

#include "src/operators/pm.h"

#include <string.h>

#include <string>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <vector>
#include <list>
#include <memory>

#include "src/operators/operator.h"
#include "src/utils/acmp.h"
#include "src/utils/string.h"

namespace modsecurity {
namespace operators {

Pm::~Pm() {
    acmp_node_t *root = m_p->root_node;
    acmp_node_t *node = root;

    cleanup(root);

    free(m_p);
    m_p = NULL;
#ifdef MODSEC_MUTEX_ON_PM
    pthread_mutex_destroy(&m_lock);
#endif
}

void Pm::cleanup(acmp_node_t *n) {
    if (n == NULL) {
        return;
    }

    cleanup(n->sibling);
    cleanup(n->child);

    postOrderTraversal(n->btree);

    if (n->text && strlen(n->text) > 0) {
        free(n->text);
        n->text = NULL;
    }

    if (n->pattern && strlen(n->pattern) > 0) {
        free(n->pattern);
        n->pattern = NULL;
    }

    free(n);
}

void Pm::postOrderTraversal(acmp_btree_node_t *node) {
    if (node == NULL) {
        return;
    }

    postOrderTraversal(node->right);
    postOrderTraversal(node->left);

    free(node);
}

bool Pm::evaluate(Transaction *transaction, Rule *rule,
    const std::string &input, std::shared_ptr<RuleMessage> ruleMessage) {
    int rc = -1;
    ACMPT pt;
    pt.parser = m_p;
    pt.ptr = NULL;
    const char *match = NULL;
#ifdef MODSEC_MUTEX_ON_PM
    pthread_mutex_lock(&m_lock);
#endif
    rc = acmp_process_quick(&pt, &match, input.c_str(), input.length());
#ifdef MODSEC_MUTEX_ON_PM
    pthread_mutex_unlock(&m_lock);
#endif

    if (rc >= 0 && transaction) {
        std::string match_(match);
        logOffset(ruleMessage, rc - match_.size() + 1, match_.size());
        transaction->m_matched.push_back(match_);
    }

    if (rule && rule->m_containsCaptureAction && transaction && rc >= 0) {
        transaction->m_collections.m_tx_collection->storeOrUpdateFirst("0",
            std::string(match));
        ms_dbg_a(transaction, 7, "Added pm match TX.0: " + \
            std::string(match));
    }

    return rc >= 0;
}

bool Pm::init(const std::string &file, std::string *error) {
    std::vector<std::string> vec;
    std::istringstream *iss;
    const char *err = NULL;

#ifdef MODSEC_MUTEX_ON_PM
    pthread_mutex_init(&m_lock, NULL);
#endif
    char *content = parse_pm_content(m_param.c_str(), m_param.length(), &err);
    if (content == NULL) {
        iss = new std::istringstream(m_param);
    } else {
        iss = new std::istringstream(content);
    }

    std::copy(std::istream_iterator<std::string>(*iss),
        std::istream_iterator<std::string>(),
        back_inserter(vec));

    for (auto &a : vec) {
        acmp_add_pattern(m_p, a.c_str(), NULL, NULL, a.length());
    }

    while (m_p->is_failtree_done == 0) {
        acmp_prepare(m_p);
    }

    if (content) {
        free(content);
        content = NULL;
    }

    delete iss;

    return true;
}

}  // namespace operators
}  // namespace modsecurity
<|endoftext|>


<commit_before>/*
    accountconfig.cpp  -  Kopete account config page

    Copyright (c) 2003-2004 by Olivier Goffart        <ogoffart @ kde.org>
    Copyright (c) 2003      by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2003-2004 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "kopeteaccountconfig.h"

#include <qcheckbox.h>
#include <qlayout.h>

#include <kcolorbutton.h>
#include <kpushbutton.h>
#include <kdebug.h>
#include <kdialogbase.h>
#include <kgenericfactory.h>
#include <kiconloader.h>
#include <klistview.h>
#include <klocale.h>
#include <kmessagebox.h>

#include "addaccountwizard.h"
#include "editaccountwidget.h"
#include "kopeteaccountconfigbase.h"
#include "kopeteaccountmanager.h"
#include "kopeteprotocol.h"
#include "kopeteaccount.h"

class KopeteAccountLVI : public KListViewItem
{
	public:
		KopeteAccountLVI( Kopete::Account *a, KListView *p ) : KListViewItem( p ){  m_account = a; }
		Kopete::Account *account() { return m_account; }

	private:
		Kopete::Account *m_account;
};

typedef KGenericFactory<KopeteAccountConfig, QWidget> KopeteAccountConfigFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_kopete_accountconfig, KopeteAccountConfigFactory( "kcm_kopete_accountconfig" ) )

KopeteAccountConfig::KopeteAccountConfig( QWidget *parent, const char * /* name */, const QStringList &args )
: KCModule( KopeteAccountConfigFactory::instance(), parent, args )
{

	( new QVBoxLayout( this ) )->setAutoAdd( true );
	m_view = new KopeteAccountConfigBase( this, "KopeteAccountConfig::m_view" );

	m_view->mButtonUp->setIconSet( SmallIconSet( "up" ) );
	m_view->mButtonDown->setIconSet( SmallIconSet( "down" ) );

	connect( m_view->mButtonNew,    SIGNAL( clicked() ), this, SLOT( slotAddAccount() ) );
	connect( m_view->mButtonEdit,   SIGNAL( clicked() ), this, SLOT( slotEditAccount() ) );
	connect( m_view->mButtonRemove, SIGNAL( clicked() ), this, SLOT( slotRemoveAccount() ) );
	connect( m_view->mButtonUp,     SIGNAL( clicked() ), this, SLOT( slotAccountUp() ) );
	connect( m_view->mButtonDown,   SIGNAL( clicked() ), this, SLOT( slotAccountDown() ) );
	connect( m_view->mAccountList,  SIGNAL( selectionChanged() ), this, SLOT( slotItemSelected() ) );
	connect( m_view->mAccountList,  SIGNAL( doubleClicked( QListViewItem * ) ), this, SLOT( slotEditAccount() ) );
	connect( m_view->mUseColor,     SIGNAL( toggled( bool ) ), this, SLOT( slotColorChanged() ) );
	connect( m_view->mColorButton,  SIGNAL( changed( const QColor & ) ), this, SLOT( slotColorChanged() ) );

	m_view->mAccountList->setSorting(-1);

	setButtons( Help );
	load();
}

void KopeteAccountConfig::save()
{
	uint priority = m_view->mAccountList->childCount();

	KopeteAccountLVI *i = static_cast<KopeteAccountLVI*>( m_view->mAccountList->firstChild() );
	while( i )
	{
		  i->account()->setPriority( priority-- );
		  i = static_cast<KopeteAccountLVI*>( i->nextSibling() );
	}

	QMap<Kopete::Account *, QColor>::Iterator it;
	for(it=m_newColors.begin() ; it != m_newColors.end() ; ++it)
		it.key()->setColor(it.data());
	m_newColors.clear();

	Kopete::AccountManager::self()->save();

	load(); //refresh the colred accounts (in case of apply)
}

void KopeteAccountConfig::load()
{
	KopeteAccountLVI *lvi = 0L;

	m_view->mAccountList->clear();

	QPtrList<Kopete::Account> accounts = Kopete::AccountManager::self()->accounts();
	for ( Kopete::Account *i = accounts.first() ; i; i = accounts.next() )
	{
		// Insert the item after the previous one
		lvi = new KopeteAccountLVI( i, m_view->mAccountList );
		lvi->setText( 0, i->protocol()->displayName() );
		lvi->setPixmap( 0, i->accountIcon() );
		lvi->setText( 1, i->accountLabel() );
	}

	m_newColors.clear();
	slotItemSelected();
}

void KopeteAccountConfig::slotItemSelected()
{
	m_protected=true;
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );

	m_view->mButtonEdit->setEnabled( itemSelected );
	m_view->mButtonRemove->setEnabled( itemSelected );

	if ( itemSelected )
	{
		m_view->mButtonUp->setEnabled( itemSelected->itemAbove() );
		m_view->mButtonDown->setEnabled( itemSelected->itemBelow() );

		Kopete::Account *account = itemSelected->account();
		QColor color= m_newColors.contains(account) ? m_newColors[account] :  account->color();
		m_view->mUseColor->setEnabled( true );
		m_view->mUseColor->setChecked( color.isValid() );
		m_view->mColorButton->setColor( color );
		m_view->mColorButton->setEnabled( m_view->mUseColor->isChecked() );

	}
	else
	{
		m_view->mButtonUp->setEnabled( false );
		m_view->mButtonDown->setEnabled( false);
		m_view->mUseColor->setEnabled( false );
		m_view->mColorButton->setEnabled( false );
	}
	m_protected=false;
}

void KopeteAccountConfig::slotAccountUp()
{
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !itemSelected )
		return;

	if ( itemSelected->itemAbove() )
		itemSelected->itemAbove()->moveItem( itemSelected );

	slotItemSelected();
	emit changed( true );
}

void KopeteAccountConfig::slotAccountDown()
{
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !itemSelected )
		return;

	itemSelected->moveItem( itemSelected->itemBelow() );

	slotItemSelected();
	emit changed( true );
}

void KopeteAccountConfig::slotAddAccount()
{
	AddAccountWizard *m_addwizard = new AddAccountWizard( this, "addAccountWizard", true );
	connect( m_addwizard, SIGNAL( destroyed( QObject * ) ), this, SLOT( slotAddWizardDone() ) );
	m_addwizard->show();
}

void KopeteAccountConfig::slotEditAccount()
{
	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi )
		return;

	Kopete::Account *ident = lvi->account();
	Kopete::Protocol *proto = ident->protocol();

	KDialogBase *editDialog = new KDialogBase( this, "KopeteAccountConfig::editDialog", true,
		i18n( "Edit Account" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true );

	KopeteEditAccountWidget *m_accountWidget = proto->createEditAccountWidget( ident, editDialog );
	if ( !m_accountWidget )
		return;

	// FIXME: Why the #### is EditAccountWidget not a QWidget?!? This sideways casting
	//        is braindead and error-prone. Looking at MSN the only reason I can see is
	//        because it allows direct subclassing of designer widgets. But what is
	//        wrong with embedding the designer widget in an empty QWidget instead?
	//        Also, if this REALLY has to be a pure class and not a widget, then the
	//        class should at least be renamed to EditAccountIface instead - Martijn
	QWidget *w = dynamic_cast<QWidget *>( m_accountWidget );
	if ( !w )
		return;

	editDialog->setMainWidget( w );
	if ( editDialog->exec() == QDialog::Accepted )
	{
		if( m_accountWidget->validateData() )
			m_accountWidget->apply();
	}

	// FIXME: Why deleteLater? It shouldn't be in use anymore at this point - Martijn
	editDialog->deleteLater();
	load();
	Kopete::AccountManager::self()->save();
}

void KopeteAccountConfig::slotRemoveAccount()
{
	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi )
		return;

	Kopete::Account *i = lvi->account();
	if ( KMessageBox::warningContinueCancel( this, i18n( "Are you sure you want to remove the account \"%1\"?" ).arg( i->accountLabel() ),
		i18n( "Remove Account" ), KGuiItem(i18n( "Remove Account" ), "editdelete"),
		 "askRemoveAccount", KMessageBox::Notify | KMessageBox::Dangerous ) == KMessageBox::Continue )
	{
		Kopete::AccountManager::self()->removeAccount( i );
		delete lvi;
	}
}

void KopeteAccountConfig::slotAddWizardDone()
{
	save();
	load();
}

void KopeteAccountConfig::slotColorChanged()
{
	if(m_protected)  //this slot is called because we changed the button
		return;      // color because another account has been selected

	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi )
		return;
	Kopete::Account *account = lvi->account();

	if(!account->color().isValid() && !m_view->mUseColor->isChecked() )
	{  //we don't use color for that account and nothing changed.
		m_newColors.remove(account);
		return;
	}
	else if(!m_view->mUseColor->isChecked())
	{  //the user disabled account coloring, but it was activated before
		m_newColors[account]=QColor();
		emit changed(true);
		return;
	}
	else if(account->color() == m_view->mColorButton->color() )
	{   //The color has not changed.
		m_newColors.remove(account);
		return;
	}
	else
	{
		m_newColors[account]=m_view->mColorButton->color();
		emit changed(true);
	}
}

#include "kopeteaccountconfig.moc"

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>fix crash that happen when removing jabber accounts that have transports<commit_after>/*
    accountconfig.cpp  -  Kopete account config page

    Copyright (c) 2003-2004 by Olivier Goffart        <ogoffart @ kde.org>
    Copyright (c) 2003      by Martijn Klingens       <klingens@kde.org>

    Kopete    (c) 2003-2004 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "kopeteaccountconfig.h"

#include <qcheckbox.h>
#include <qlayout.h>
#include <qguardedptr.h>

#include <kcolorbutton.h>
#include <kpushbutton.h>
#include <kdebug.h>
#include <kdialogbase.h>
#include <kgenericfactory.h>
#include <kiconloader.h>
#include <klistview.h>
#include <klocale.h>
#include <kmessagebox.h>

#include "addaccountwizard.h"
#include "editaccountwidget.h"
#include "kopeteaccountconfigbase.h"
#include "kopeteaccountmanager.h"
#include "kopeteprotocol.h"
#include "kopeteaccount.h"

class KopeteAccountLVI : public KListViewItem
{
	public:
		KopeteAccountLVI( Kopete::Account *a, KListView *p ) : KListViewItem( p ){  m_account = a; }
		Kopete::Account *account() { return m_account; }

	private:
		//need to be guarded because some accounts may be linked (that's the case of jabber transports)
		QGuardedPtr<Kopete::Account> m_account;
};

typedef KGenericFactory<KopeteAccountConfig, QWidget> KopeteAccountConfigFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_kopete_accountconfig, KopeteAccountConfigFactory( "kcm_kopete_accountconfig" ) )

KopeteAccountConfig::KopeteAccountConfig( QWidget *parent, const char * /* name */, const QStringList &args )
: KCModule( KopeteAccountConfigFactory::instance(), parent, args )
{

	( new QVBoxLayout( this ) )->setAutoAdd( true );
	m_view = new KopeteAccountConfigBase( this, "KopeteAccountConfig::m_view" );

	m_view->mButtonUp->setIconSet( SmallIconSet( "up" ) );
	m_view->mButtonDown->setIconSet( SmallIconSet( "down" ) );

	connect( m_view->mButtonNew,    SIGNAL( clicked() ), this, SLOT( slotAddAccount() ) );
	connect( m_view->mButtonEdit,   SIGNAL( clicked() ), this, SLOT( slotEditAccount() ) );
	connect( m_view->mButtonRemove, SIGNAL( clicked() ), this, SLOT( slotRemoveAccount() ) );
	connect( m_view->mButtonUp,     SIGNAL( clicked() ), this, SLOT( slotAccountUp() ) );
	connect( m_view->mButtonDown,   SIGNAL( clicked() ), this, SLOT( slotAccountDown() ) );
	connect( m_view->mAccountList,  SIGNAL( selectionChanged() ), this, SLOT( slotItemSelected() ) );
	connect( m_view->mAccountList,  SIGNAL( doubleClicked( QListViewItem * ) ), this, SLOT( slotEditAccount() ) );
	connect( m_view->mUseColor,     SIGNAL( toggled( bool ) ), this, SLOT( slotColorChanged() ) );
	connect( m_view->mColorButton,  SIGNAL( changed( const QColor & ) ), this, SLOT( slotColorChanged() ) );

	m_view->mAccountList->setSorting(-1);

	setButtons( Help );
	load();
}

void KopeteAccountConfig::save()
{
	uint priority = m_view->mAccountList->childCount();

	KopeteAccountLVI *i = static_cast<KopeteAccountLVI*>( m_view->mAccountList->firstChild() );
	while( i )
	{
		if(!i->account())
			continue;
		i->account()->setPriority( priority-- );
		i = static_cast<KopeteAccountLVI*>( i->nextSibling() );
	}

	QMap<Kopete::Account *, QColor>::Iterator it;
	for(it=m_newColors.begin() ; it != m_newColors.end() ; ++it)
		it.key()->setColor(it.data());
	m_newColors.clear();

	Kopete::AccountManager::self()->save();

	load(); //refresh the colred accounts (in case of apply)
}

void KopeteAccountConfig::load()
{
	KopeteAccountLVI *lvi = 0L;

	m_view->mAccountList->clear();

	QPtrList<Kopete::Account> accounts = Kopete::AccountManager::self()->accounts();
	for ( Kopete::Account *i = accounts.first() ; i; i = accounts.next() )
	{
		// Insert the item after the previous one
		lvi = new KopeteAccountLVI( i, m_view->mAccountList );
		lvi->setText( 0, i->protocol()->displayName() );
		lvi->setPixmap( 0, i->accountIcon() );
		lvi->setText( 1, i->accountLabel() );
	}

	m_newColors.clear();
	slotItemSelected();
}

void KopeteAccountConfig::slotItemSelected()
{
	m_protected=true;
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );

	m_view->mButtonEdit->setEnabled( itemSelected );
	m_view->mButtonRemove->setEnabled( itemSelected );

	if ( itemSelected &&  itemSelected->account() )
	{
		m_view->mButtonUp->setEnabled( itemSelected->itemAbove() );
		m_view->mButtonDown->setEnabled( itemSelected->itemBelow() );

		Kopete::Account *account = itemSelected->account();
		QColor color= m_newColors.contains(account) ? m_newColors[account] :  account->color();
		m_view->mUseColor->setEnabled( true );
		m_view->mUseColor->setChecked( color.isValid() );
		m_view->mColorButton->setColor( color );
		m_view->mColorButton->setEnabled( m_view->mUseColor->isChecked() );

	}
	else
	{
		m_view->mButtonUp->setEnabled( false );
		m_view->mButtonDown->setEnabled( false);
		m_view->mUseColor->setEnabled( false );
		m_view->mColorButton->setEnabled( false );
	}
	m_protected=false;
}

void KopeteAccountConfig::slotAccountUp()
{
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !itemSelected )
		return;

	if ( itemSelected->itemAbove() )
		itemSelected->itemAbove()->moveItem( itemSelected );

	slotItemSelected();
	emit changed( true );
}

void KopeteAccountConfig::slotAccountDown()
{
	KopeteAccountLVI *itemSelected = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !itemSelected )
		return;

	itemSelected->moveItem( itemSelected->itemBelow() );

	slotItemSelected();
	emit changed( true );
}

void KopeteAccountConfig::slotAddAccount()
{
	AddAccountWizard *m_addwizard = new AddAccountWizard( this, "addAccountWizard", true );
	connect( m_addwizard, SIGNAL( destroyed( QObject * ) ), this, SLOT( slotAddWizardDone() ) );
	m_addwizard->show();
}

void KopeteAccountConfig::slotEditAccount()
{
	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi || !lvi->account() )
		return;

	Kopete::Account *ident = lvi->account();
	Kopete::Protocol *proto = ident->protocol();

	KDialogBase *editDialog = new KDialogBase( this, "KopeteAccountConfig::editDialog", true,
		i18n( "Edit Account" ), KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true );

	KopeteEditAccountWidget *m_accountWidget = proto->createEditAccountWidget( ident, editDialog );
	if ( !m_accountWidget )
		return;

	// FIXME: Why the #### is EditAccountWidget not a QWidget?!? This sideways casting
	//        is braindead and error-prone. Looking at MSN the only reason I can see is
	//        because it allows direct subclassing of designer widgets. But what is
	//        wrong with embedding the designer widget in an empty QWidget instead?
	//        Also, if this REALLY has to be a pure class and not a widget, then the
	//        class should at least be renamed to EditAccountIface instead - Martijn
	QWidget *w = dynamic_cast<QWidget *>( m_accountWidget );
	if ( !w )
		return;

	editDialog->setMainWidget( w );
	if ( editDialog->exec() == QDialog::Accepted )
	{
		if( m_accountWidget->validateData() )
			m_accountWidget->apply();
	}

	// FIXME: Why deleteLater? It shouldn't be in use anymore at this point - Martijn
	editDialog->deleteLater();
	load();
	Kopete::AccountManager::self()->save();
}

void KopeteAccountConfig::slotRemoveAccount()
{
	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi || !lvi->account() )
		return;

	Kopete::Account *i = lvi->account();
	if ( KMessageBox::warningContinueCancel( this, i18n( "Are you sure you want to remove the account \"%1\"?" ).arg( i->accountLabel() ),
		i18n( "Remove Account" ), KGuiItem(i18n( "Remove Account" ), "editdelete"),
		 "askRemoveAccount", KMessageBox::Notify | KMessageBox::Dangerous ) == KMessageBox::Continue )
	{
		Kopete::AccountManager::self()->removeAccount( i );
		delete lvi;
	}
}

void KopeteAccountConfig::slotAddWizardDone()
{
	save();
	load();
}

void KopeteAccountConfig::slotColorChanged()
{
	if(m_protected)  //this slot is called because we changed the button
		return;      // color because another account has been selected

	KopeteAccountLVI *lvi = static_cast<KopeteAccountLVI*>( m_view->mAccountList->selectedItem() );
	if ( !lvi || !lvi->account() )
		return;
	Kopete::Account *account = lvi->account();

	if(!account->color().isValid() && !m_view->mUseColor->isChecked() )
	{  //we don't use color for that account and nothing changed.
		m_newColors.remove(account);
		return;
	}
	else if(!m_view->mUseColor->isChecked())
	{  //the user disabled account coloring, but it was activated before
		m_newColors[account]=QColor();
		emit changed(true);
		return;
	}
	else if(account->color() == m_view->mColorButton->color() )
	{   //The color has not changed.
		m_newColors.remove(account);
		return;
	}
	else
	{
		m_newColors[account]=m_view->mColorButton->color();
		emit changed(true);
	}
}

#include "kopeteaccountconfig.moc"

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>/************************************************************************
	filename: 	CEGUIPropertyHelper.cpp
	created:	6/7/2004
	author:		Paul D Turner

	purpose:	Implementation of PropertyHelper methods
*************************************************************************/
/*************************************************************************
    Crazy Eddie's GUI System (http://crayzedsgui.sourceforge.net)
    Copyright (C)2004 Paul D Turner (crayzed@users.sourceforge.net)

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*************************************************************************/
#include "CEGUIPropertyHelper.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIExceptions.h"

#include <cstdio>

// Start of CEGUI namespace section
namespace CEGUI
{
float PropertyHelper::stringToFloat(const String& str)
{
	using namespace std;

	float val = 0;
	sscanf(str.c_str(), " %f", &val);

	return val;
}

uint PropertyHelper::stringToUint(const String& str)
{
	using namespace std;

	uint val = 0;
	sscanf(str.c_str(), " %u", &val);

	return val;
}

bool PropertyHelper::stringToBool(const String& str)
{
	if (str == (utf8*)"True")
	{
		return true;
	}
	else
	{
		return false;
	}

}

Size PropertyHelper::stringToSize(const String& str)
{
	using namespace std;

	Size val(0,0);
	sscanf(str.c_str(), " w:%f h:%f", &val.d_width, &val.d_height);

	return val;
}

Point PropertyHelper::stringToPoint(const String& str)
{
	using namespace std;

	Point val(0,0) ;
	sscanf(str.c_str(), " x:%f y:%f", &val.d_x, &val.d_y);

	return val;
}

Rect PropertyHelper::stringToRect(const String& str)
{
	using namespace std;

	Rect val(0, 0, 0, 0);
	sscanf(str.c_str(), " l:%f t:%f r:%f b:%f", &val.d_left, &val.d_top, &val.d_right, &val.d_bottom);

	return val;
}

MetricsMode PropertyHelper::stringToMetricsMode(const String& str)
{
	if (str == (utf8*)"Relative")
	{
		return Relative;
	}
	else if (str == (utf8*)"Absolute")
	{
		return Absolute;
	}
	else
	{
		return Inherited;
	}

}

const Image* PropertyHelper::stringToImage(const String& str)
{
	using namespace std;

	char imageSet[128];
	char imageName[128];

	sscanf(str.c_str(), " set:%127s image:%127s", imageSet, imageName);

	const Image* image;

	try
	{
		image = &ImagesetManager::getSingleton().getImageset((utf8*)imageSet)->getImage((utf8*)imageName);
	}
	catch (UnknownObjectException)
	{
		image = NULL;
	}

	return image;
}

String PropertyHelper::floatToString(float val)
{
	using namespace std;

	char buff[64];
	sprintf(buff, "%f", val);

	return String((utf8*)buff);
}

String PropertyHelper::uintToString(uint val)
{
	using namespace std;

	char buff[64];
	sprintf(buff, "%u", val);

	return String((utf8*)buff);
}

String PropertyHelper::boolToString(bool val)
{
	if (val)
	{
		return String((utf8*)"True");
	}
	else
	{
		return String ((utf8*)"False");
	}

}

String PropertyHelper::sizeToString(const Size& val)
{
	using namespace std;

	char buff[128];
	sprintf(buff, "w:%f h:%f", val.d_width, val.d_height);

	return String((utf8*)buff);
}

String PropertyHelper::pointToString(const Point& val)
{
	using namespace std;

	char buff[128];
	sprintf(buff, "x:%f y:%f", val.d_x, val.d_y);

	return String((utf8*)buff);
}

String PropertyHelper::rectToString(const Rect& val)
{
	using namespace std;

	char buff[256];
	sprintf(buff, "l:%f t:%f r:%f b:%f", val.d_left, val.d_top, val.d_right, val.d_bottom);

	return String((utf8*)buff);
}

String PropertyHelper::metricsModeToString(MetricsMode val)
{
	if (val == Relative)
	{
		return String((utf8*)"Relative");
	}
	else if (val == Absolute)
	{
		return String((utf8*)"Absolute");
	}
	else
	{
		return String((utf8*)"Inherited");
	}

}

String PropertyHelper::imageToString(const Image* const val)
{
	if (val != NULL)
	{
		return String((utf8*)"set:" + val->getImagesetName() + (utf8*)" image:" + val->getName());
	}

	return String((utf8*)"");
}

String PropertyHelper::colourToString(colour val)
{
	using namespace std;

	char buff[16];
	sprintf(buff, "%.8X", val);

	return String((utf8*)buff);
}

colour PropertyHelper::stringToColour(const String& str)
{
	using namespace std;

	colour val = 0xFF000000;
	sscanf(str.c_str(), " %8X", &val);

	return val;

}

String PropertyHelper::colourRectToString(const ColourRect& val)
{
	using namespace std;

	char buff[64];
	sprintf(buff, "tl:%.8X tr:%.8X bl:%.8X br:%.8X", val.d_top_left, val.d_top_right, val.d_bottom_left, val.d_bottom_right);

	return String((utf8*)buff);
}

ColourRect PropertyHelper::stringToColourRect(const String& str)
{
	using namespace std;

	ColourRect val(0xFF000000);
	sscanf(str.c_str(), "tl:%8X tr:%8X bl:%8X br:%8X", &val.d_top_left, &val.d_top_right, &val.d_bottom_left, &val.d_bottom_right);

	return val;
}

} // End of  CEGUI namespace section
<commit_msg>Added support so that true for boolean properties can be either "True" or "true" instead of just "True" (anything else still == false).<commit_after>/************************************************************************
	filename: 	CEGUIPropertyHelper.cpp
	created:	6/7/2004
	author:		Paul D Turner

	purpose:	Implementation of PropertyHelper methods
*************************************************************************/
/*************************************************************************
    Crazy Eddie's GUI System (http://crayzedsgui.sourceforge.net)
    Copyright (C)2004 Paul D Turner (crayzed@users.sourceforge.net)

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*************************************************************************/
#include "CEGUIPropertyHelper.h"
#include "CEGUIImagesetManager.h"
#include "CEGUIImageset.h"
#include "CEGUIExceptions.h"

#include <cstdio>

// Start of CEGUI namespace section
namespace CEGUI
{
float PropertyHelper::stringToFloat(const String& str)
{
	using namespace std;

	float val = 0;
	sscanf(str.c_str(), " %f", &val);

	return val;
}

uint PropertyHelper::stringToUint(const String& str)
{
	using namespace std;

	uint val = 0;
	sscanf(str.c_str(), " %u", &val);

	return val;
}

bool PropertyHelper::stringToBool(const String& str)
{
	if ((str == (utf8*)"True") || (str == (utf8*)"true"))
	{
		return true;
	}
	else
	{
		return false;
	}

}

Size PropertyHelper::stringToSize(const String& str)
{
	using namespace std;

	Size val(0,0);
	sscanf(str.c_str(), " w:%f h:%f", &val.d_width, &val.d_height);

	return val;
}

Point PropertyHelper::stringToPoint(const String& str)
{
	using namespace std;

	Point val(0,0) ;
	sscanf(str.c_str(), " x:%f y:%f", &val.d_x, &val.d_y);

	return val;
}

Rect PropertyHelper::stringToRect(const String& str)
{
	using namespace std;

	Rect val(0, 0, 0, 0);
	sscanf(str.c_str(), " l:%f t:%f r:%f b:%f", &val.d_left, &val.d_top, &val.d_right, &val.d_bottom);

	return val;
}

MetricsMode PropertyHelper::stringToMetricsMode(const String& str)
{
	if (str == (utf8*)"Relative")
	{
		return Relative;
	}
	else if (str == (utf8*)"Absolute")
	{
		return Absolute;
	}
	else
	{
		return Inherited;
	}

}

const Image* PropertyHelper::stringToImage(const String& str)
{
	using namespace std;

	char imageSet[128];
	char imageName[128];

	sscanf(str.c_str(), " set:%127s image:%127s", imageSet, imageName);

	const Image* image;

	try
	{
		image = &ImagesetManager::getSingleton().getImageset((utf8*)imageSet)->getImage((utf8*)imageName);
	}
	catch (UnknownObjectException)
	{
		image = NULL;
	}

	return image;
}

String PropertyHelper::floatToString(float val)
{
	using namespace std;

	char buff[64];
	sprintf(buff, "%f", val);

	return String((utf8*)buff);
}

String PropertyHelper::uintToString(uint val)
{
	using namespace std;

	char buff[64];
	sprintf(buff, "%u", val);

	return String((utf8*)buff);
}

String PropertyHelper::boolToString(bool val)
{
	if (val)
	{
		return String((utf8*)"True");
	}
	else
	{
		return String ((utf8*)"False");
	}

}

String PropertyHelper::sizeToString(const Size& val)
{
	using namespace std;

	char buff[128];
	sprintf(buff, "w:%f h:%f", val.d_width, val.d_height);

	return String((utf8*)buff);
}

String PropertyHelper::pointToString(const Point& val)
{
	using namespace std;

	char buff[128];
	sprintf(buff, "x:%f y:%f", val.d_x, val.d_y);

	return String((utf8*)buff);
}

String PropertyHelper::rectToString(const Rect& val)
{
	using namespace std;

	char buff[256];
	sprintf(buff, "l:%f t:%f r:%f b:%f", val.d_left, val.d_top, val.d_right, val.d_bottom);

	return String((utf8*)buff);
}

String PropertyHelper::metricsModeToString(MetricsMode val)
{
	if (val == Relative)
	{
		return String((utf8*)"Relative");
	}
	else if (val == Absolute)
	{
		return String((utf8*)"Absolute");
	}
	else
	{
		return String((utf8*)"Inherited");
	}

}

String PropertyHelper::imageToString(const Image* const val)
{
	if (val != NULL)
	{
		return String((utf8*)"set:" + val->getImagesetName() + (utf8*)" image:" + val->getName());
	}

	return String((utf8*)"");
}

String PropertyHelper::colourToString(colour val)
{
	using namespace std;

	char buff[16];
	sprintf(buff, "%.8X", val);

	return String((utf8*)buff);
}

colour PropertyHelper::stringToColour(const String& str)
{
	using namespace std;

	colour val = 0xFF000000;
	sscanf(str.c_str(), " %8X", &val);

	return val;

}

String PropertyHelper::colourRectToString(const ColourRect& val)
{
	using namespace std;

	char buff[64];
	sprintf(buff, "tl:%.8X tr:%.8X bl:%.8X br:%.8X", val.d_top_left, val.d_top_right, val.d_bottom_left, val.d_bottom_right);

	return String((utf8*)buff);
}

ColourRect PropertyHelper::stringToColourRect(const String& str)
{
	using namespace std;

	ColourRect val(0xFF000000);
	sscanf(str.c_str(), "tl:%8X tr:%8X bl:%8X br:%8X", &val.d_top_left, &val.d_top_right, &val.d_bottom_left, &val.d_bottom_right);

	return val;
}

} // End of  CEGUI namespace section
<|endoftext|>