<commit_before>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 */
#include <ch_ethz_tell_ClientManager.h>
#include <tellstore/ClientConfig.hpp>
#include <tellstore/ClientManager.hpp>
#include "clientManager.h"

using namespace tell::store;

using ImplementationDetails = telljava::ClientManager;

crossbow::string to_string(JNIEnv* env, jstring str) {
    auto ptr = env->GetStringUTFChars(str, nullptr);
    crossbow::string res(ptr, env->GetStringUTFLength(str));
    env->ReleaseStringUTFChars(str, ptr);
    return ptr;
}

jlong Java_ch_ethz_tell_ClientManager_getClientManagerPtr(JNIEnv*, jclass, jlong impl) {
    auto o = reinterpret_cast<ImplementationDetails*>(impl);
    return reinterpret_cast<jlong>(&o->clientManager);
}

jlong Java_ch_ethz_tell_ClientManager_getScanMemoryManagerPtr(JNIEnv*, jclass, jlong impl) {
    auto o = reinterpret_cast<ImplementationDetails*>(impl);
    return reinterpret_cast<jlong>(&o->scanMemoryManager);
}

jlong Java_ch_ethz_tell_ClientManager_init(JNIEnv* env,
        jobject self,
        jstring commitManager,
        jstring tellStore,
        jlong chunkCount,
        jlong chunkSize)
{
    auto cM = to_string(env, commitManager);
    auto tS = to_string(env, tellStore);
    ClientConfig config;
    config.commitManager = ClientConfig::parseCommitManager(cM);
    config.tellStore = ClientConfig::parseTellStore(tS);
    auto res = new ImplementationDetails(std::move(config));
    res->scanMemoryManager = std::move(res->clientManager.allocateScanMemory(size_t(chunkCount), size_t(chunkSize)));
    return reinterpret_cast<jlong>(res);
}

void Java_ch_ethz_tell_ClientManager_shutdown(JNIEnv* env, jobject, jlong ptr) {
    delete reinterpret_cast<ImplementationDetails*>(ptr);
}

/* getters and setters for configuration */

void Java_ch_ethz_tell_ClientManager_setMaxPendingResponsesImpl(JNIEnv*, jobject, jlong obj, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(obj);
    o->mConfig.maxPendingResponses = value;
}

jlong Java_ch_ethz_tell_ClientManager_getMaxPendingResponsesImpl(JNIEnv*, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.maxPendingResponses;
}

void Java_ch_ethz_tell_ClientManager_setNumNetworkThreadsImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.numNetworkThreads = value;
}

jlong Java_ch_ethz_tell_ClientManager_getNumNetworkThreadsImpl(JNIEnv *, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.numNetworkThreads;
}

void Java_ch_ethz_tell_ClientManager_setReceiveBufferCountImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.receiveBufferCount = value;
}

jlong Java_ch_ethz_tell_ClientManager_getReceiveBufferCountImpl(JNIEnv *, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.receiveBufferCount;
}

void Java_ch_ethz_tell_ClientManager_setSendBufferCountImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.sendBufferCount = value;
}

jlong Java_ch_ethz_tell_ClientManager_getSendBufferCountImpl(JNIEnv *, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.sendBufferCount;
}

void Java_ch_ethz_tell_ClientManager_setBufferLengthImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.bufferLength = value;
}

jlong Java_ch_ethz_tell_ClientManager_getBufferLengthImpl(JNIEnv *, jobject self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.bufferLength;
}

void Java_ch_ethz_tell_ClientManager_setCompletionQueueLengthImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.completionQueueLength = value;
}

jlong Java_ch_ethz_tell_ClientManager_getCompletionQueueLengthImpl(JNIEnv *, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.completionQueueLength;
}

void Java_ch_ethz_tell_ClientManager_setSendQueueLengthImpl(JNIEnv*, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.sendQueueLength = value;
}

jlong Java_ch_ethz_tell_ClientManager_getSendQueueLengthImpl(JNIEnv*, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.sendQueueLength;
}

<commit_msg>Return the actual string in to_string<commit_after>/*
 * (C) Copyright 2015 ETH Zurich Systems Group (http://www.systems.ethz.ch/) and others.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Contributors:
 *     Markus Pilman <mpilman@inf.ethz.ch>
 *     Simon Loesing <sloesing@inf.ethz.ch>
 *     Thomas Etter <etterth@gmail.com>
 *     Kevin Bocksrocker <kevin.bocksrocker@gmail.com>
 *     Lucas Braun <braunl@inf.ethz.ch>
 */
#include <ch_ethz_tell_ClientManager.h>
#include <tellstore/ClientConfig.hpp>
#include <tellstore/ClientManager.hpp>
#include "clientManager.h"

using namespace tell::store;

using ImplementationDetails = telljava::ClientManager;

crossbow::string to_string(JNIEnv* env, jstring str) {
    auto ptr = env->GetStringUTFChars(str, nullptr);
    crossbow::string res(ptr, env->GetStringUTFLength(str));
    env->ReleaseStringUTFChars(str, ptr);
    return res;
}

jlong Java_ch_ethz_tell_ClientManager_getClientManagerPtr(JNIEnv*, jclass, jlong impl) {
    auto o = reinterpret_cast<ImplementationDetails*>(impl);
    return reinterpret_cast<jlong>(&o->clientManager);
}

jlong Java_ch_ethz_tell_ClientManager_getScanMemoryManagerPtr(JNIEnv*, jclass, jlong impl) {
    auto o = reinterpret_cast<ImplementationDetails*>(impl);
    return reinterpret_cast<jlong>(&o->scanMemoryManager);
}

jlong Java_ch_ethz_tell_ClientManager_init(JNIEnv* env,
        jobject self,
        jstring commitManager,
        jstring tellStore,
        jlong chunkCount,
        jlong chunkSize)
{
    auto cM = to_string(env, commitManager);
    auto tS = to_string(env, tellStore);
    ClientConfig config;
    config.commitManager = ClientConfig::parseCommitManager(cM);
    config.tellStore = ClientConfig::parseTellStore(tS);
    auto res = new ImplementationDetails(std::move(config));
    res->scanMemoryManager = std::move(res->clientManager.allocateScanMemory(size_t(chunkCount), size_t(chunkSize)));
    return reinterpret_cast<jlong>(res);
}

void Java_ch_ethz_tell_ClientManager_shutdown(JNIEnv* env, jobject, jlong ptr) {
    delete reinterpret_cast<ImplementationDetails*>(ptr);
}

/* getters and setters for configuration */

void Java_ch_ethz_tell_ClientManager_setMaxPendingResponsesImpl(JNIEnv*, jobject, jlong obj, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(obj);
    o->mConfig.maxPendingResponses = value;
}

jlong Java_ch_ethz_tell_ClientManager_getMaxPendingResponsesImpl(JNIEnv*, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.maxPendingResponses;
}

void Java_ch_ethz_tell_ClientManager_setNumNetworkThreadsImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.numNetworkThreads = value;
}

jlong Java_ch_ethz_tell_ClientManager_getNumNetworkThreadsImpl(JNIEnv *, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.numNetworkThreads;
}

void Java_ch_ethz_tell_ClientManager_setReceiveBufferCountImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.receiveBufferCount = value;
}

jlong Java_ch_ethz_tell_ClientManager_getReceiveBufferCountImpl(JNIEnv *, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.receiveBufferCount;
}

void Java_ch_ethz_tell_ClientManager_setSendBufferCountImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.sendBufferCount = value;
}

jlong Java_ch_ethz_tell_ClientManager_getSendBufferCountImpl(JNIEnv *, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.sendBufferCount;
}

void Java_ch_ethz_tell_ClientManager_setBufferLengthImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.bufferLength = value;
}

jlong Java_ch_ethz_tell_ClientManager_getBufferLengthImpl(JNIEnv *, jobject self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.bufferLength;
}

void Java_ch_ethz_tell_ClientManager_setCompletionQueueLengthImpl(JNIEnv *, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.completionQueueLength = value;
}

jlong Java_ch_ethz_tell_ClientManager_getCompletionQueueLengthImpl(JNIEnv *, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.completionQueueLength;
}

void Java_ch_ethz_tell_ClientManager_setSendQueueLengthImpl(JNIEnv*, jobject, jlong self, jlong value) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    o->mConfig.infinibandConfig.sendQueueLength = value;
}

jlong Java_ch_ethz_tell_ClientManager_getSendQueueLengthImpl(JNIEnv*, jobject, jlong self) {
    auto o = reinterpret_cast<ImplementationDetails*>(self);
    return o->mConfig.infinibandConfig.sendQueueLength;
}

<|endoftext|>


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

#include "chainparams.h"
#include "glcnotificationinterface.h"
#include "validation.h"

void CGLCNotificationInterface::InitializeCurrentBlockTip()
{
    LOCK(cs_main);
    UpdatedBlockTip(chainActive.Tip(), NULL, IsInitialBlockDownload());
}

void CGLCNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
{
    if (pindexNew == pindexFork) // blocks were disconnected without any new ones
        return;

    // Update global GIP1 activation status
    if(Params().GetConsensus().GIP1Height != -1)
        fGIP1ActiveAtTip = pindexNew->nHeight >= Params().GetConsensus().GIP1Height;
    else
        fGIP1ActiveAtTip = pindexNew->GetMedianTimePast() >= Params().GetConsensus().GIP1ActivationTime;

    if (fInitialDownload)
        return;

}

void CGLCNotificationInterface::SyncTransaction(const CTransaction &tx, const CBlockIndex *pindex, int posInBlock)
{

}

<commit_msg>Revert GIP1 Changes<commit_after><|endoftext|>


<commit_before>/**
 * @file cache.cpp
 *
 */

#include "cache.h"
#include "info.h"
#include "logger.h"
#include "plugin_factory.h"
#include <boost/lexical_cast.hpp>
#include <time.h>

using namespace std;
using namespace himan::plugin;

typedef lock_guard<mutex> Lock;

cache::cache()
{
	itsLogger = logger("cache");
}
string cache::UniqueName(const info& info)
{
	stringstream ss;

	// clang-format off

	ss << info.Producer().Id() << "_"
	   << info.Time().OriginDateTime().String("%Y-%m-%d %H:%M:%S") << "_"
	   << info.Time().ValidDateTime().String("%Y-%m-%d %H:%M:%S") << "_"
	   << info.Param().Name() << "_"
	   << static_cast<string>(info.Level()) << "_"
	   << info.ForecastType().Type() << "_"
	   << info.ForecastType().Value();

	// clang-format on

	return ss.str();
}

string cache::UniqueNameFromOptions(search_options& options)
{
	ASSERT(options.configuration->DatabaseType() == kNoDatabase || options.prod.Id() != kHPMissingInt);
	stringstream ss;

	// clang-format off

	ss << options.prod.Id() << "_"
	   << options.time.OriginDateTime().String("%Y-%m-%d %H:%M:%S") << "_"
	   << options.time.ValidDateTime().String("%Y-%m-%d %H:%M:%S") << "_"
	   << options.param.Name() << "_"
	   << static_cast<string>(options.level) << "_"
	   << options.ftype.Type() << "_"
	   << options.ftype.Value();

	// clang-format on

	return ss.str();
}

void cache::Insert(info_t anInfo, bool pin)
{
	SplitToPool(anInfo, pin);
}
void cache::SplitToPool(info_t anInfo, bool pin)
{
	auto localInfo = make_shared<info>(*anInfo);

	// Cached data is never replaced by another data that has
	// the same uniqueName

	const string uniqueName = UniqueName(*localInfo);

	if (cache_pool::Instance()->Find(uniqueName))
	{
		itsLogger.Trace("Data with key " + uniqueName + " already exists at cache");

		// Update timestamp of this cache item
		cache_pool::Instance()->UpdateTime(uniqueName);
		return;
	}

#ifdef HAVE_CUDA
	if (localInfo->Grid()->IsPackedData())
	{
		itsLogger.Trace("Removing packed data from cached info");
		localInfo->Grid()->PackedData().Clear();
	}
#endif

	ASSERT(!localInfo->Grid()->IsPackedData());

	cache_pool::Instance()->Insert(uniqueName, localInfo, pin);
}

vector<shared_ptr<himan::info>> cache::GetInfo(search_options& options)
{
	string uniqueName = UniqueNameFromOptions(options);

	vector<shared_ptr<himan::info>> info;

	if (cache_pool::Instance()->Find(uniqueName))
	{
		info.push_back(cache_pool::Instance()->GetInfo(uniqueName));
		itsLogger.Trace("Found matching data for " + uniqueName);
	}

	return info;
}

void cache::Clean()
{
	cache_pool::Instance()->Clean();
}
size_t cache::Size() const
{
	return cache_pool::Instance()->Size();
}
cache_pool* cache_pool::itsInstance = NULL;

cache_pool::cache_pool() : itsCacheLimit(-1)
{
	itsLogger = logger("cache_pool");
}

cache_pool* cache_pool::Instance()
{
	if (!itsInstance)
	{
		itsInstance = new cache_pool();
	}

	return itsInstance;
}

void cache_pool::CacheLimit(int theCacheLimit)
{
	itsCacheLimit = theCacheLimit;
}
bool cache_pool::Find(const string& uniqueName)
{
	Lock lock(itsAccessMutex);
	return itsCache.count(uniqueName) > 0;
}
void cache_pool::Insert(const string& uniqueName, shared_ptr<himan::info> anInfo, bool pin)
{
	cache_item item;
	item.info = anInfo;
	item.access_time = time(nullptr);
	item.pinned = pin;

	{
		Lock lock(itsAccessMutex);

		itsCache.insert(pair<string, cache_item>(uniqueName, item));
	}

	itsLogger.Trace("Data added to cache with name: " + uniqueName + ", pinned: " + to_string(pin));

	if (itsCacheLimit > -1 && itsCache.size() > static_cast<size_t>(itsCacheLimit))
	{
		Clean();
	}
}

void cache_pool::UpdateTime(const std::string& uniqueName)
{
	Lock lock(itsAccessMutex);
	itsCache[uniqueName].access_time = time(nullptr);
}
void cache_pool::Clean()
{
	ASSERT(itsCacheLimit > 0);
	if (itsCache.size() <= static_cast<size_t>(itsCacheLimit))
	{
		return;
	}

	string oldestName;
	time_t oldestTime = INT_MAX;

	{
		Lock lock(itsAccessMutex);

		for (const auto& kv : itsCache)
		{
			if (kv.second.access_time < oldestTime && !kv.second.pinned)
			{
				oldestName = kv.first;
				oldestTime = kv.second.access_time;
			}
		}

		ASSERT(!oldestName.empty());

		itsCache.erase(oldestName);
	}

	itsLogger.Trace("Data cleared from cache: " + oldestName + " with time: " + to_string(oldestTime));
	itsLogger.Trace("Cache size: " + to_string(itsCache.size()));
}

shared_ptr<himan::info> cache_pool::GetInfo(const string& uniqueName)
{
	Lock lock(itsAccessMutex);

	return make_shared<info>(*itsCache[uniqueName].info);
}

size_t cache_pool::Size() const
{
	return itsCache.size();
}
<commit_msg>Split info before putting it to cache, but avoid copying memory<commit_after>/**
 * @file cache.cpp
 *
 */

#include "cache.h"
#include "info.h"
#include "logger.h"
#include "plugin_factory.h"
#include <boost/lexical_cast.hpp>
#include <time.h>

using namespace std;
using namespace himan::plugin;

typedef lock_guard<mutex> Lock;

cache::cache()
{
	itsLogger = logger("cache");
}
string cache::UniqueName(const info& info)
{
	stringstream ss;

	// clang-format off

	ss << info.Producer().Id() << "_"
	   << info.Time().OriginDateTime().String("%Y-%m-%d %H:%M:%S") << "_"
	   << info.Time().ValidDateTime().String("%Y-%m-%d %H:%M:%S") << "_"
	   << info.Param().Name() << "_"
	   << static_cast<string>(info.Level()) << "_"
	   << info.ForecastType().Type() << "_"
	   << info.ForecastType().Value();

	// clang-format on

	return ss.str();
}

string cache::UniqueNameFromOptions(search_options& options)
{
	ASSERT(options.configuration->DatabaseType() == kNoDatabase || options.prod.Id() != kHPMissingInt);
	stringstream ss;

	// clang-format off

	ss << options.prod.Id() << "_"
	   << options.time.OriginDateTime().String("%Y-%m-%d %H:%M:%S") << "_"
	   << options.time.ValidDateTime().String("%Y-%m-%d %H:%M:%S") << "_"
	   << options.param.Name() << "_"
	   << static_cast<string>(options.level) << "_"
	   << options.ftype.Type() << "_"
	   << options.ftype.Value();

	// clang-format on

	return ss.str();
}

void cache::Insert(info_t anInfo, bool pin)
{
	SplitToPool(anInfo, pin);
}
void cache::SplitToPool(info_t anInfo, bool pin)
{
	auto localInfo = make_shared<info>(*anInfo);

	// Cached data is never replaced by another data that has
	// the same uniqueName

	const string uniqueName = UniqueName(*localInfo);

	if (cache_pool::Instance()->Find(uniqueName))
	{
		itsLogger.Trace("Data with key " + uniqueName + " already exists at cache");

		// Update timestamp of this cache item
		cache_pool::Instance()->UpdateTime(uniqueName);
		return;
	}

#ifdef HAVE_CUDA
	if (localInfo->Grid()->IsPackedData())
	{
		itsLogger.Trace("Removing packed data from cached info");
		localInfo->Grid()->PackedData().Clear();
	}
#endif

	ASSERT(!localInfo->Grid()->IsPackedData());

	// localInfo might contain multiple grids. When adding data to cache, we need
	// to make sure that single info contains only single grid.

	if (localInfo->DimensionSize() > 1)
	{
		auto newInfo = make_shared<info>(localInfo->ForecastType(), localInfo->Time(), localInfo->Level(), localInfo->Param());
		newInfo->Grid(localInfo->SharedGrid());
		localInfo = newInfo;
	}

	ASSERT(localInfo->DimensionSize() == 1);
	cache_pool::Instance()->Insert(uniqueName, localInfo, pin);
}

vector<shared_ptr<himan::info>> cache::GetInfo(search_options& options)
{
	string uniqueName = UniqueNameFromOptions(options);

	vector<shared_ptr<himan::info>> info;

	if (cache_pool::Instance()->Find(uniqueName))
	{
		info.push_back(cache_pool::Instance()->GetInfo(uniqueName));
		itsLogger.Trace("Found matching data for " + uniqueName);
	}

	return info;
}

void cache::Clean()
{
	cache_pool::Instance()->Clean();
}
size_t cache::Size() const
{
	return cache_pool::Instance()->Size();
}
cache_pool* cache_pool::itsInstance = NULL;

cache_pool::cache_pool() : itsCacheLimit(-1)
{
	itsLogger = logger("cache_pool");
}

cache_pool* cache_pool::Instance()
{
	if (!itsInstance)
	{
		itsInstance = new cache_pool();
	}

	return itsInstance;
}

void cache_pool::CacheLimit(int theCacheLimit)
{
	itsCacheLimit = theCacheLimit;
}
bool cache_pool::Find(const string& uniqueName)
{
	Lock lock(itsAccessMutex);
	return itsCache.count(uniqueName) > 0;
}
void cache_pool::Insert(const string& uniqueName, shared_ptr<himan::info> anInfo, bool pin)
{
	cache_item item;
	item.info = anInfo;
	item.access_time = time(nullptr);
	item.pinned = pin;

	{
		Lock lock(itsAccessMutex);

		itsCache.insert(pair<string, cache_item>(uniqueName, item));
	}

	itsLogger.Trace("Data added to cache with name: " + uniqueName + ", pinned: " + to_string(pin));

	if (itsCacheLimit > -1 && itsCache.size() > static_cast<size_t>(itsCacheLimit))
	{
		Clean();
	}
}

void cache_pool::UpdateTime(const std::string& uniqueName)
{
	Lock lock(itsAccessMutex);
	itsCache[uniqueName].access_time = time(nullptr);
}
void cache_pool::Clean()
{
	ASSERT(itsCacheLimit > 0);
	if (itsCache.size() <= static_cast<size_t>(itsCacheLimit))
	{
		return;
	}

	string oldestName;
	time_t oldestTime = INT_MAX;

	{
		Lock lock(itsAccessMutex);

		for (const auto& kv : itsCache)
		{
			if (kv.second.access_time < oldestTime && !kv.second.pinned)
			{
				oldestName = kv.first;
				oldestTime = kv.second.access_time;
			}
		}

		ASSERT(!oldestName.empty());

		itsCache.erase(oldestName);
	}

	itsLogger.Trace("Data cleared from cache: " + oldestName + " with time: " + to_string(oldestTime));
	itsLogger.Trace("Cache size: " + to_string(itsCache.size()));
}

shared_ptr<himan::info> cache_pool::GetInfo(const string& uniqueName)
{
	Lock lock(itsAccessMutex);

	return make_shared<info>(*itsCache[uniqueName].info);
}

size_t cache_pool::Size() const
{
	return itsCache.size();
}
<|endoftext|>


<commit_before>// kmmsgbase.cpp

#include "kmmsgbase.h"
#include <mimelib/mimepp.h>
#include <qregexp.h>
#ifndef KRN
#include <kmfolder.h>
#endif

#include <ctype.h>

#define NUM_STATUSLIST 9
static KMMsgStatus sStatusList[NUM_STATUSLIST] =
{
  KMMsgStatusDeleted, KMMsgStatusNew,
  KMMsgStatusUnread,  KMMsgStatusOld,
  KMMsgStatusRead,    KMMsgStatusReplied,
  KMMsgStatusSent,    KMMsgStatusQueued,
  KMMsgStatusUnknown /* "Unknown" must be at the *end* of the list */
};

//-----------------------------------------------------------------------------
KMMsgBase::KMMsgBase(KMFolder* aParent)
{
  mParent  = aParent;
  mDirty   = FALSE;
  mMsgSize = 0;
  mFolderOffset = 0;
  mStatus  = KMMsgStatusNew;
  mDate    = 0;
}

//-----------------------------------------------------------------------------
KMMsgBase::~KMMsgBase()
{
}

//-----------------------------------------------------------------------------
void KMMsgBase::assign(const KMMsgBase* other)
{
  mParent = other->mParent;
  mDirty  = other->mDirty;
  mMsgSize = other->mMsgSize;
  mFolderOffset = other->mFolderOffset;
  mStatus = other->mStatus;
  mDate = other->mDate;
}

//-----------------------------------------------------------------------------
KMMsgBase& KMMsgBase::operator=(const KMMsgBase& other)
{
  assign(&other);
  return *this;
}

//-----------------------------------------------------------------------------
bool KMMsgBase::isMessage(void) const
{
  return FALSE;
}

//-----------------------------------------------------------------------------
void KMMsgBase::setStatus(KMMsgStatus aStatus)
{
  if (mParent) mParent->msgStatusChanged( mStatus, aStatus );
  mStatus = aStatus;
  mDirty = TRUE;
#ifndef KRN
  if (mParent) mParent->headerOfMsgChanged(this);
#endif
}

//-----------------------------------------------------------------------------
void KMMsgBase::setStatus(const char* aStatusStr, const char* aXStatusStr)
{
  int i;

  mStatus = KMMsgStatusUnknown;

  // first try to find status from "X-Status" field if given
  if (aXStatusStr) for (i=0; i<NUM_STATUSLIST-1; i++)
  {
    if (strchr(aXStatusStr, (char)sStatusList[i]))
    {
      mStatus = sStatusList[i];
      break;
    }
  }

  // if not successful then use the "Status" field
  if (mStatus == KMMsgStatusUnknown)
  {
    if (aStatusStr &&
        ((aStatusStr[0]=='R' && aStatusStr[1]=='O') ||
	 (aStatusStr[0]=='O' && aStatusStr[1]=='R')))
	mStatus=KMMsgStatusOld;
    else if (aStatusStr && aStatusStr[0]=='R') mStatus=KMMsgStatusRead;
    else if (aStatusStr && aStatusStr[0]=='D') mStatus=KMMsgStatusDeleted;
    else mStatus=KMMsgStatusNew;
  }

  mDirty = TRUE;
#ifndef KRN
  if (mParent) mParent->headerOfMsgChanged(this);
#endif
}

//-----------------------------------------------------------------------------
KMMsgStatus KMMsgBase::status(void) const
{
  return mStatus;
}

//-----------------------------------------------------------------------------
bool KMMsgBase::isUnread(void) const
{
  KMMsgStatus st = status();
  return (st==KMMsgStatusNew || st==KMMsgStatusUnread);
}

//-----------------------------------------------------------------------------
bool KMMsgBase::isNew(void) const
{
  KMMsgStatus st = status();
  return (st==KMMsgStatusNew);
}

//-----------------------------------------------------------------------------
const char* KMMsgBase::statusToStr(KMMsgStatus aStatus)
{
  static char sstr[2];

  sstr[0] = (char)aStatus;
  sstr[1] = '\0';

  return sstr;
}

//-----------------------------------------------------------------------------
void KMMsgBase::setDate(const time_t aUnixTime)
{
  mDate  = aUnixTime;
  mDirty = TRUE;
}

//-----------------------------------------------------------------------------
void KMMsgBase::setDate(const char* aDateStr)
{
  DwDateTime dwDate;

  dwDate.FromString(aDateStr);
  dwDate.Parse();
  mDate  = dwDate.AsUnixTime();
  mDirty = TRUE;
}

//-----------------------------------------------------------------------------
time_t KMMsgBase::date(void) const
{
  return mDate;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::dateStr(void) const
{
  return ctime(&mDate);
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::asIndexString(void) const
{
  int i, len;
  QString str;
  unsigned long dateTen = date();
  dateTen %= 10000000000; // In index only 10 chars are reserved for the date

  QString a((const char*)decodeQuotedPrintableString(subject()));
  a.truncate(100);
  QString b((const char*)decodeQuotedPrintableString(from()));
  b.truncate(100);
  QString c((const char*)decodeQuotedPrintableString(to()));
  c.truncate(100);

  // don't forget to change indexStringLength() below !!
  str.sprintf("%c %-.9lu %-.9lu %-.10lu %-3.3s ",
	      (char)status(), folderOffset(), msgSize(), dateTen,
	      (const char*)xmark() );
  if (str.length() != 37)
    debug( "Invalid length " + str );
  str += a.rightJustify( 100, ' ' );
  str += " ";
  str += b.rightJustify( 100, ' ' );
  str += " ";
  str += c.rightJustify( 100, ' ' );

  len = str.length();
  for (i=0; i<len; i++)
    if (str[i] < ' ' && str[i] >= 0)
      str[i] = ' ';

  if (str.length() != 339) {
    debug( QString( "Error invalid index entry %1").arg(str.length()) );
    debug( str );
  }
  return str;
}

//-----------------------------------------------------------------------------
int KMMsgBase::indexStringLength(void)
{
  //return 237;
  //  return 338; //sven (+ 100 chars to + one space, right?
  return 339; //sanders (use 10 digits for the date we need this in 2001!)
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareByIndex(const KMMsgBase* other) const
{
  return (mFolderOffset - other->mFolderOffset);
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareBySubject(const KMMsgBase* other) const
{
  //const char *subjStr, *otherSubjStr;
  bool hasKeywd, otherHasKeywd;
  int rc;

  QString subjStr = skipKeyword(subject(), ':', &hasKeywd);
  QString otherSubjStr = skipKeyword(other->subject(), ':', &otherHasKeywd);

  rc = stricmp(subjStr, otherSubjStr);
  if (rc) return rc;

  // If both are equal return the one with a keyword (Re: / Fwd: /...)
  // at the beginning as the larger one.
  return (hasKeywd - otherHasKeywd);
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareByStatus(const KMMsgBase* other) const
{
  KMMsgStatus stat;
  int i;

  for (i=NUM_STATUSLIST-1; i>0; i--)
  {
    stat = sStatusList[i];
    if (mStatus==stat || other->mStatus==stat) break;
  }

  return ((mStatus==stat) - (other->mStatus==stat));
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareByDate(const KMMsgBase* other) const
{
  return (mDate - other->mDate);
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareByFrom(const KMMsgBase* other) const
{
  const char *f, *fo;

  f = from();
  fo = other->from();

  if (!f || !fo) return ((!fo) - (!f));

  while (*f && *f<'A') f++;
  while (*fo && *fo<'A') fo++;

  return stricmp(f, fo);
}

//-----------------------------------------------------------------------------
QString KMMsgBase::skipKeyword(const QString aStr, char sepChar,
				   bool* hasKeyword)
{
  int i, maxChars=3;
  const char *pos, *str = aStr.data();

  if (!str) return 0;

  while (*str==' ')
    str++;
  if (hasKeyword) *hasKeyword=FALSE;

  for (i=0,pos=str; *pos && i<maxChars; pos++,i++)
  {
    if (*pos < 'A' || *pos == sepChar) break;
  }

  if (i>1 && *pos == sepChar) // skip following spaces too
  {
    for (pos++; *pos==' '; pos++)
      ;
    if (hasKeyword) *hasKeyword=TRUE;
    return pos;
  }
  return str;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::decodeRFC1522String(const QString _str)
{
  QCString aStr = _str.ascii();
  QCString result;
  char *pos, *dest, *beg, *end, *mid;
  QString str;
  char encoding, ch;
  bool valid;
  const int maxLen=200;
  int i;

  if (aStr.find("=?") < 0) return aStr;

  result.truncate(aStr.length());
  for (pos=aStr.data(), dest=result.data(); *pos; pos++)
  {
    if (pos[0]!='=' || pos[1]!='?')
    {
      *dest++ = *pos;
      continue;
    }
    beg = pos+2;
    end = beg;
    valid = TRUE;
    // parse charset name
    for (i=2,pos+=2; i<maxLen && (*pos!='?'&&(ispunct(*pos)||isalnum(*pos))); i++)
      pos++;
    if (*pos!='?' || i<4 || i>=maxLen) valid = FALSE;
    else
    {
      // get encoding and check delimiting question marks
      encoding = toupper(pos[1]);
      if (pos[2]!='?' || (encoding!='Q' && encoding!='B'))
	valid = FALSE;
      pos+=3;
      i+=3;
    }
    if (valid)
    {
      mid = pos;
      // search for end of encoded part
      while (i<maxLen && *pos && !(*pos=='?' && *(pos+1)=='='))
      {
	i++;
	pos++;
      }
      end = pos+2;//end now points to the first char after the encoded string
      if (i>=maxLen || !*pos) valid = FALSE;
    }
    if (valid)
    {
      ch = *pos;
      *pos = '\0';
      str = QString(mid).left((int)(mid - pos - 1));
      if (encoding == 'Q')
      {
	// decode quoted printable text
	for (i=str.length()-1; i>=0; i--)
	  if (str[i]=='_') str[i]=' ';
	str = decodeQuotedPrintable(str);
      }
      else
      {
	// decode base64 text
	str = decodeBase64(str);
      }
      *pos = ch;
      for (i=0; i < (int)str.length(); i++)
	*dest++ = (char)(QChar)str[i];

      pos = end -1;
    }
    else
    {
      //result += "=?";
      //pos = beg -1; // because pos gets increased shortly afterwards
      pos = beg - 2;
      *dest++ = *pos++;
      *dest++ = *pos;
    }
  }
  *dest = '\0';
  return result;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::decodeQuotedPrintableString(const QString aStr)
{
#ifdef BROKEN
  static QString result;
  int start, beg, mid, end;
  end = 0; // Remove compiler warning;

  start = 0;
  end = 0;
  result = "";

  while (1)
  {
    beg = aStr.find("=?", start);
    if (beg < 0)
    {
      // no more suspicious string parts found -- done
      result += aStr.mid(start, 32767);
      break;
    }

    if (beg > start) result += aStr.mid(start, beg-start);
    mid = aStr.find("?Q?", beg+2);
    if (mid>beg) end = aStr.find("?=", mid+3);
    if (mid < 0 || end < 0)
    {
      // no quoted printable part -- skip it
      result += "=?";
      start += 2;
      continue;
    }
    if (aStr[mid+3]=='_' )
    {
      result += ' ';
      mid++;
    }
    else if (aStr[mid+3]==' ') mid++;

    if (end-mid-3 > 0)
      result += decodeQuotedPrintable(aStr.mid(mid+3, end-mid-3).data());
    start = end+2;
  }
  return result;
#else
  return decodeRFC1522String(aStr);
#endif
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::decodeQuotedPrintable(const QString aStr)
{
  DwString dwsrc(aStr.data());
  DwString dwdest;

  DwDecodeQuotedPrintable(dwsrc, dwdest);
  return dwdest.c_str();
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::encodeQuotedPrintable(const QString aStr)
{
  DwString dwsrc(aStr.data(), aStr.length());
  DwString dwdest;
  QString result;

  DwEncodeQuotedPrintable(dwsrc, dwdest);
  result = dwdest.c_str();
  return result;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::decodeBase64(const QString aStr)
{
  DwString dwsrc(aStr.data(), aStr.length());
  DwString dwdest;
  QString result;

  DwDecodeBase64(dwsrc, dwdest);
  result = dwdest.c_str();
  return result;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::encodeBase64(const QString aStr)
{
  DwString dwsrc(aStr.data(), aStr.length());
  DwString dwdest;
  QString result;

  DwEncodeBase64(dwsrc, dwdest);
  result = dwdest.c_str();
  return result;
}
<commit_msg>Fix compilation with gcc 2.96<commit_after>// kmmsgbase.cpp

#include "kmmsgbase.h"
#include <mimelib/mimepp.h>
#include <qregexp.h>
#ifndef KRN
#include <kmfolder.h>
#endif

#include <ctype.h>

#define NUM_STATUSLIST 9
static KMMsgStatus sStatusList[NUM_STATUSLIST] =
{
  KMMsgStatusDeleted, KMMsgStatusNew,
  KMMsgStatusUnread,  KMMsgStatusOld,
  KMMsgStatusRead,    KMMsgStatusReplied,
  KMMsgStatusSent,    KMMsgStatusQueued,
  KMMsgStatusUnknown /* "Unknown" must be at the *end* of the list */
};

//-----------------------------------------------------------------------------
KMMsgBase::KMMsgBase(KMFolder* aParent)
{
  mParent  = aParent;
  mDirty   = FALSE;
  mMsgSize = 0;
  mFolderOffset = 0;
  mStatus  = KMMsgStatusNew;
  mDate    = 0;
}

//-----------------------------------------------------------------------------
KMMsgBase::~KMMsgBase()
{
}

//-----------------------------------------------------------------------------
void KMMsgBase::assign(const KMMsgBase* other)
{
  mParent = other->mParent;
  mDirty  = other->mDirty;
  mMsgSize = other->mMsgSize;
  mFolderOffset = other->mFolderOffset;
  mStatus = other->mStatus;
  mDate = other->mDate;
}

//-----------------------------------------------------------------------------
KMMsgBase& KMMsgBase::operator=(const KMMsgBase& other)
{
  assign(&other);
  return *this;
}

//-----------------------------------------------------------------------------
bool KMMsgBase::isMessage(void) const
{
  return FALSE;
}

//-----------------------------------------------------------------------------
void KMMsgBase::setStatus(KMMsgStatus aStatus)
{
  if (mParent) mParent->msgStatusChanged( mStatus, aStatus );
  mStatus = aStatus;
  mDirty = TRUE;
#ifndef KRN
  if (mParent) mParent->headerOfMsgChanged(this);
#endif
}

//-----------------------------------------------------------------------------
void KMMsgBase::setStatus(const char* aStatusStr, const char* aXStatusStr)
{
  int i;

  mStatus = KMMsgStatusUnknown;

  // first try to find status from "X-Status" field if given
  if (aXStatusStr) for (i=0; i<NUM_STATUSLIST-1; i++)
  {
    if (strchr(aXStatusStr, (char)sStatusList[i]))
    {
      mStatus = sStatusList[i];
      break;
    }
  }

  // if not successful then use the "Status" field
  if (mStatus == KMMsgStatusUnknown)
  {
    if (aStatusStr &&
        ((aStatusStr[0]=='R' && aStatusStr[1]=='O') ||
	 (aStatusStr[0]=='O' && aStatusStr[1]=='R')))
	mStatus=KMMsgStatusOld;
    else if (aStatusStr && aStatusStr[0]=='R') mStatus=KMMsgStatusRead;
    else if (aStatusStr && aStatusStr[0]=='D') mStatus=KMMsgStatusDeleted;
    else mStatus=KMMsgStatusNew;
  }

  mDirty = TRUE;
#ifndef KRN
  if (mParent) mParent->headerOfMsgChanged(this);
#endif
}

//-----------------------------------------------------------------------------
KMMsgStatus KMMsgBase::status(void) const
{
  return mStatus;
}

//-----------------------------------------------------------------------------
bool KMMsgBase::isUnread(void) const
{
  KMMsgStatus st = status();
  return (st==KMMsgStatusNew || st==KMMsgStatusUnread);
}

//-----------------------------------------------------------------------------
bool KMMsgBase::isNew(void) const
{
  KMMsgStatus st = status();
  return (st==KMMsgStatusNew);
}

//-----------------------------------------------------------------------------
const char* KMMsgBase::statusToStr(KMMsgStatus aStatus)
{
  static char sstr[2];

  sstr[0] = (char)aStatus;
  sstr[1] = '\0';

  return sstr;
}

//-----------------------------------------------------------------------------
void KMMsgBase::setDate(const time_t aUnixTime)
{
  mDate  = aUnixTime;
  mDirty = TRUE;
}

//-----------------------------------------------------------------------------
void KMMsgBase::setDate(const char* aDateStr)
{
  DwDateTime dwDate;

  dwDate.FromString(aDateStr);
  dwDate.Parse();
  mDate  = dwDate.AsUnixTime();
  mDirty = TRUE;
}

//-----------------------------------------------------------------------------
time_t KMMsgBase::date(void) const
{
  return mDate;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::dateStr(void) const
{
  return ctime(&mDate);
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::asIndexString(void) const
{
  int i, len;
  QString str;
  unsigned long dateTen = date();
//  dateTen %= 10000000000; // In index only 10 chars are reserved for the date
//  This is nonsense because 10000000000 is bigger than the highest unsigned
//  long. (Or is there any compiler that defines unsigned long as something
//  really huge??)

  QString a((const char*)decodeQuotedPrintableString(subject()));
  a.truncate(100);
  QString b((const char*)decodeQuotedPrintableString(from()));
  b.truncate(100);
  QString c((const char*)decodeQuotedPrintableString(to()));
  c.truncate(100);

  // don't forget to change indexStringLength() below !!
  str.sprintf("%c %-.9lu %-.9lu %-.10lu %-3.3s ",
	      (char)status(), folderOffset(), msgSize(), dateTen,
	      (const char*)xmark() );
  if (str.length() != 37)
    debug( "Invalid length " + str );
  str += a.rightJustify( 100, ' ' );
  str += " ";
  str += b.rightJustify( 100, ' ' );
  str += " ";
  str += c.rightJustify( 100, ' ' );

  len = str.length();
  for (i=0; i<len; i++)
    if (str[i] < ' ' && str[i] >= 0)
      str[i] = ' ';

  if (str.length() != 339) {
    debug( QString( "Error invalid index entry %1").arg(str.length()) );
    debug( str );
  }
  return str;
}

//-----------------------------------------------------------------------------
int KMMsgBase::indexStringLength(void)
{
  //return 237;
  //  return 338; //sven (+ 100 chars to + one space, right?
  return 339; //sanders (use 10 digits for the date we need this in 2001!)
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareByIndex(const KMMsgBase* other) const
{
  return (mFolderOffset - other->mFolderOffset);
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareBySubject(const KMMsgBase* other) const
{
  //const char *subjStr, *otherSubjStr;
  bool hasKeywd, otherHasKeywd;
  int rc;

  QString subjStr = skipKeyword(subject(), ':', &hasKeywd);
  QString otherSubjStr = skipKeyword(other->subject(), ':', &otherHasKeywd);

  rc = stricmp(subjStr, otherSubjStr);
  if (rc) return rc;

  // If both are equal return the one with a keyword (Re: / Fwd: /...)
  // at the beginning as the larger one.
  return (hasKeywd - otherHasKeywd);
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareByStatus(const KMMsgBase* other) const
{
  KMMsgStatus stat;
  int i;

  for (i=NUM_STATUSLIST-1; i>0; i--)
  {
    stat = sStatusList[i];
    if (mStatus==stat || other->mStatus==stat) break;
  }

  return ((mStatus==stat) - (other->mStatus==stat));
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareByDate(const KMMsgBase* other) const
{
  return (mDate - other->mDate);
}

//-----------------------------------------------------------------------------
int KMMsgBase::compareByFrom(const KMMsgBase* other) const
{
  const char *f, *fo;

  f = from();
  fo = other->from();

  if (!f || !fo) return ((!fo) - (!f));

  while (*f && *f<'A') f++;
  while (*fo && *fo<'A') fo++;

  return stricmp(f, fo);
}

//-----------------------------------------------------------------------------
QString KMMsgBase::skipKeyword(const QString aStr, char sepChar,
				   bool* hasKeyword)
{
  int i, maxChars=3;
  const char *pos, *str = aStr.data();

  if (!str) return 0;

  while (*str==' ')
    str++;
  if (hasKeyword) *hasKeyword=FALSE;

  for (i=0,pos=str; *pos && i<maxChars; pos++,i++)
  {
    if (*pos < 'A' || *pos == sepChar) break;
  }

  if (i>1 && *pos == sepChar) // skip following spaces too
  {
    for (pos++; *pos==' '; pos++)
      ;
    if (hasKeyword) *hasKeyword=TRUE;
    return pos;
  }
  return str;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::decodeRFC1522String(const QString _str)
{
  QCString aStr = _str.ascii();
  QCString result;
  char *pos, *dest, *beg, *end, *mid;
  QString str;
  char encoding, ch;
  bool valid;
  const int maxLen=200;
  int i;

  if (aStr.find("=?") < 0) return aStr;

  result.truncate(aStr.length());
  for (pos=aStr.data(), dest=result.data(); *pos; pos++)
  {
    if (pos[0]!='=' || pos[1]!='?')
    {
      *dest++ = *pos;
      continue;
    }
    beg = pos+2;
    end = beg;
    valid = TRUE;
    // parse charset name
    for (i=2,pos+=2; i<maxLen && (*pos!='?'&&(ispunct(*pos)||isalnum(*pos))); i++)
      pos++;
    if (*pos!='?' || i<4 || i>=maxLen) valid = FALSE;
    else
    {
      // get encoding and check delimiting question marks
      encoding = toupper(pos[1]);
      if (pos[2]!='?' || (encoding!='Q' && encoding!='B'))
	valid = FALSE;
      pos+=3;
      i+=3;
    }
    if (valid)
    {
      mid = pos;
      // search for end of encoded part
      while (i<maxLen && *pos && !(*pos=='?' && *(pos+1)=='='))
      {
	i++;
	pos++;
      }
      end = pos+2;//end now points to the first char after the encoded string
      if (i>=maxLen || !*pos) valid = FALSE;
    }
    if (valid)
    {
      ch = *pos;
      *pos = '\0';
      str = QString(mid).left((int)(mid - pos - 1));
      if (encoding == 'Q')
      {
	// decode quoted printable text
	for (i=str.length()-1; i>=0; i--)
	  if (str[i]=='_') str[i]=' ';
	str = decodeQuotedPrintable(str);
      }
      else
      {
	// decode base64 text
	str = decodeBase64(str);
      }
      *pos = ch;
      for (i=0; i < (int)str.length(); i++)
	*dest++ = (char)(QChar)str[i];

      pos = end -1;
    }
    else
    {
      //result += "=?";
      //pos = beg -1; // because pos gets increased shortly afterwards
      pos = beg - 2;
      *dest++ = *pos++;
      *dest++ = *pos;
    }
  }
  *dest = '\0';
  return result;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::decodeQuotedPrintableString(const QString aStr)
{
#ifdef BROKEN
  static QString result;
  int start, beg, mid, end;
  end = 0; // Remove compiler warning;

  start = 0;
  end = 0;
  result = "";

  while (1)
  {
    beg = aStr.find("=?", start);
    if (beg < 0)
    {
      // no more suspicious string parts found -- done
      result += aStr.mid(start, 32767);
      break;
    }

    if (beg > start) result += aStr.mid(start, beg-start);
    mid = aStr.find("?Q?", beg+2);
    if (mid>beg) end = aStr.find("?=", mid+3);
    if (mid < 0 || end < 0)
    {
      // no quoted printable part -- skip it
      result += "=?";
      start += 2;
      continue;
    }
    if (aStr[mid+3]=='_' )
    {
      result += ' ';
      mid++;
    }
    else if (aStr[mid+3]==' ') mid++;

    if (end-mid-3 > 0)
      result += decodeQuotedPrintable(aStr.mid(mid+3, end-mid-3).data());
    start = end+2;
  }
  return result;
#else
  return decodeRFC1522String(aStr);
#endif
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::decodeQuotedPrintable(const QString aStr)
{
  DwString dwsrc(aStr.data());
  DwString dwdest;

  DwDecodeQuotedPrintable(dwsrc, dwdest);
  return dwdest.c_str();
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::encodeQuotedPrintable(const QString aStr)
{
  DwString dwsrc(aStr.data(), aStr.length());
  DwString dwdest;
  QString result;

  DwEncodeQuotedPrintable(dwsrc, dwdest);
  result = dwdest.c_str();
  return result;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::decodeBase64(const QString aStr)
{
  DwString dwsrc(aStr.data(), aStr.length());
  DwString dwdest;
  QString result;

  DwDecodeBase64(dwsrc, dwdest);
  result = dwdest.c_str();
  return result;
}

//-----------------------------------------------------------------------------
const QString KMMsgBase::encodeBase64(const QString aStr)
{
  DwString dwsrc(aStr.data(), aStr.length());
  DwString dwdest;
  QString result;

  DwEncodeBase64(dwsrc, dwdest);
  result = dwdest.c_str();
  return result;
}
<|endoftext|>


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

using namespace std;
//string str;
//int counter = 0;

int get_number_without_sign(int& counter, string& str)
{
    int res = 0;
    while (counter < str.length() && str[counter] <= '9' && str[counter] >= '0')
    {
        res = res * 10 + (str[counter] - '0');
        counter++;
    }
    return res;
}

int get_number(int& counter, string& str)
{
    if (isdigit(str[counter]))
        return get_number_without_sign(counter, str);
    else
        if (str[counter] == '-')
        {
            counter++;
            return get_number_without_sign(counter, str) * (-1);
        }
        else
            throw "Unexpected symbol";
}

int get_term(int& counter, string& str)
{
    int res = get_number(counter, str);
    while (counter < str.length() && (str[counter] == '*' || str[counter] == '/'))
    {
        if (str[counter] == '*')
        {
            counter++;
            res *= get_number(counter, str);
        }
        if (str[counter] == '/')
        {
            counter++;
            res /= get_number(counter, str);
        }
    }
    return res;
}

int calculate(int& counter, string& str)
{
    int res = get_term(counter, str);
    while (counter < str.length() && (str[counter] == '+' || str[counter] == '-'))
    {
        if (str[counter] == '+')
        {
            counter++;
            res += get_term(counter, str);
        }
        if (str[counter] == '-')
        {
            counter++;
            res -= get_term(counter, str);
        }
    }
    return res;
}

void delete_spaces(string& str)
{
    for (int i = 0; i < str.length(); i++)
        if (str[i] == ' ')
        {
            str = str.erase(i, 1);
            i--;
        }
        else
        {

            if (!isdigit(str[i]))
                if(str[i] != '+' && str[i] != '-' && str[i] != '*' && str[i] != '/')
                    throw "Unexpected symbol";
            if(isalpha(str[i]))
                throw "Unexpected symbol";
        }
    if (str.length() == 0)
        throw "Empty expression";
}

int main(int argc, const char * argv[])
{
    try
    {
        string str = argv[1];
        if (argc < 2)
        {
            cout << "No expression to calculate" << endl;
            return 1;
        }
        if (str.length() == 0)
            throw "Empty expression";
        delete_spaces(str);

        int counter = 0;
        int result = calculate(counter, str);
        cout << result << endl;
        return 0;
    }

    catch (const char* str) {
        cout << str << endl;
        return 1;
    }

}
<commit_msg>Update calc.cpp<commit_after>#include <iostream>
#include <string>

using namespace std;

int get_number_without_sign(int& counter, string& str)
{
    int res = 0;
    while (counter < str.length() && str[counter] <= '9' && str[counter] >= '0')
    {
        res = res * 10 + (str[counter] - '0');
        counter++;
    }
    return res;
}

int get_number(int& counter, string& str)
{
    if (isdigit(str[counter]))
        return get_number_without_sign(counter, str);
    else
        if (str[counter] == '-')
        {
            counter++;
            return get_number_without_sign(counter, str) * (-1);
        }
        else
            throw "Unexpected symbol";
}

int get_term(int& counter, string& str)
{
    int res = get_number(counter, str);
    while (counter < str.length() && (str[counter] == '*' || str[counter] == '/'))
    {
        if (str[counter] == '*')
        {
            counter++;
            res *= get_number(counter, str);
        }
        if (str[counter] == '/')
        {
            counter++;
            int n = get_number(counter, str);
            if (n)
                res /= n;
            else
                throw "Invalid operation";

        }
    }
    return res;
}

int calculate(int& counter, string& str)
{
    int res = get_term(counter, str);
    while (counter < str.length() && (str[counter] == '+' || str[counter] == '-'))
    {
        if (str[counter] == '+')
        {
            counter++;
            res += get_term(counter, str);
        }
        if (str[counter] == '-')
        {
            counter++;
            res -= get_term(counter, str);
        }
    }
    return res;
}

void delete_spaces(string& str)
{
    for (int i = 0; i < str.length(); i++)
        if (str[i] == ' ')
        {
            str = str.erase(i, 1);
            i--;
        }
        else
        {

            if (!isdigit(str[i]))
                if(str[i] != '+' && str[i] != '-' && str[i] != '*' && str[i] != '/')
                    throw "Unexpected symbol";
            if(isalpha(str[i]))
                throw "Unexpected symbol";
        }
    if (str.length() == 0)
        throw "Empty expression";
}

int main(int argc, const char * argv[])
{
    try
    {
        string str = argv[1];
        if (argc < 2)
        {
            cout << "No expression to calculate" << endl;
            return 1;
        }
        if (str.length() == 0)
            throw "Empty expression";
        delete_spaces(str);

        int counter = 0;
        int result = calculate(counter, str);
        cout << result << endl;
        return 0;
    }

    catch (const char* str) {
        cout << str << endl;
        return 1;
    }

}
<|endoftext|>


<commit_before>/**
 * A server which is responsible for interacting with devices.
 *
 * @date                    July 7, 2014
 * @author                    Joeri HERMANS
 * @version                    0.1
 *
 * Copyright 2013 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <arpa/inet.h>
#include <cassert>
#include <cstdio>
#include <iostream>

// Application dependencies.
#include <ias/server/device_server.h>
#include <ias/server/session/device_session.h>
#include <ias/logger/logger.h>

// END Includes. /////////////////////////////////////////////////////

inline void DeviceServer::initialize( void ) {
    mSocket = nullptr;
    mListenThread = nullptr;
    mDispatchThread = nullptr;
    mFlagRunning = true;
}

void DeviceServer::setSocket( Socket * socket ) {
    // Checking the precondition.
    assert( socket != nullptr && socket->isConnected() );

    mSocket = socket;
}

void DeviceServer::setDeviceIdentifiers( const std::vector<std::string> & i ) {
    mDeviceIdentifiers = i;
}

void DeviceServer::startListenThread( void ) {
    mListenThread = new std::thread([this](){
        ServerSocket * serverSocket;
        Session * session;
        Socket * socket;

        serverSocket = getServerSocket();
        while( mFlagRunning && mSocket->isConnected() ) {
            socket = serverSocket->acceptSocket(1);
            if( socket != nullptr ) {
                logi("Starting new device session.");
                session = new DeviceSession(socket,
                                            mSocket,
                                            &mConnectedDevices,
                                            &mDeviceIdentifiers);
                session->addObserver(this);
                mSessions[session] =
                    new std::thread([session]{
                        session->run();
                        session->notifyObservers(session);
                        delete session;
                        logi("Device session terminated.");
                    });
            }
            cleanupFinishingThreads();
        }
        signalSessions();
        mSocket->closeConnection();
        while( mSessions.size() > 0 ||
               mInactiveThreads.size() > 0 ) {
            signalSessions();
            cleanupFinishingThreads();
        }
    });
}

bool DeviceServer::readBytes( char * buffer , const unsigned int n ) {
    std::size_t bytesRead;
    std::size_t nBytes;
    Reader * reader;

    // Checking the precondition.
    assert( buffer != nullptr && n > 0 );

    if( !mSocket->isConnected() ) return ( false );

    reader = mSocket->getReader();
    bytesRead = 0;
    while( bytesRead != n ) {
        nBytes = reader->readBytes(buffer + bytesRead,n - bytesRead);
        if( nBytes == 0 )
            return ( false );
        bytesRead += nBytes;
    }

    return ( true );
}

void DeviceServer::dispatchCommand( void ) {
    std::uint8_t deviceLength;
    std::uint8_t identifierLength;
    std::uint8_t parameterLength;
    std::string message;

    if( mSocket->isConnected() ) {
        if( !readBytes(reinterpret_cast<char *>(&deviceLength),1) ) return;
        if( !readBytes(reinterpret_cast<char *>(&identifierLength),1) ) return;
        if( !readBytes(reinterpret_cast<char *>(&parameterLength),1) ) return;
        char deviceIdentifier[deviceLength + 1];
        char identifier[identifierLength + 1];
        char parameter[parameterLength + 1];
        if( !readBytes(deviceIdentifier,deviceLength) ) return;
        if( !readBytes(identifier,identifierLength) ) return;
        if( parameterLength > 0 && !readBytes(parameter,parameterLength) )
            return;
        deviceIdentifier[deviceLength] = 0;
        identifier[identifierLength] = 0;
        parameter[parameterLength] = 0;
        // Format the message
        message += 0x01;
        message += identifierLength;
        message += parameterLength;
        message.append(identifier);
        message.append(parameter);
        mConnectedDevices.dispatch(deviceIdentifier,message);
    } else {
        stop();
    }
}

void DeviceServer::startDispatchThread( void ) {
    mDispatchThread = new std::thread([this](){
        std::size_t nBytes;
        std::uint8_t type;
        Reader * reader;
        bool heartbeatSend = false;

        setServerTimeouts();
        reader = mSocket->getReader();
        while( mFlagRunning && mSocket->isConnected() ) {
            type = 0xff;
            nBytes = reader->readByte(reinterpret_cast<char *>(&type));
            std::cout << "Is connected: " << std::to_string(mSocket->isConnected()) << std::endl << std::flush;
            if( nBytes == 0 ) {
                if( !serverHeartbeat() || heartbeatSend ) {
                    loge("B");
                    stop();
                } else {
                    heartbeatSend = true;
                }
                continue;
            }
            switch(type) {
            case 0x00:
                if( !heartbeatSend )
                    serverHeartbeat();
                break;
            case 0x01:
                dispatchCommand();
                break;
            default:
                mFlagRunning = false;
                break;
            }
            heartbeatSend = false;
        }
        stop();
    });
}

void DeviceServer::signalSessions( void ) {
    std::map<Session *,std::thread *>::iterator it;

    mMutexSessions.lock();
    for( it = mSessions.begin() ; it != mSessions.end() ; ++it )
        it->first->stop();
    mMutexSessions.unlock();
}

void DeviceServer::cleanupFinishingThreads( void ) {
    std::thread * t;

    while( mInactiveThreads.size() > 0 ) {
        t = mInactiveThreads.front();
        if( t != nullptr ) {
            t->join();
            delete t;
        }
        mInactiveThreads.erase(mInactiveThreads.begin());
    }
}

bool DeviceServer::serverHeartbeat( void ) {
    static const std::int8_t beat = 0x00;
    Writer * writer;
    bool ok;

    writer = mSocket->getWriter();
    ok = (writer->writeBytes(reinterpret_cast<const char *>(&beat),1) == 1);

    return ( ok );
}

void DeviceServer::setServerTimeouts( void ) {
    struct timeval tv;

    tv.tv_sec = 20;
    tv.tv_usec = 0;
    mSocket->setReceiveTimeout(tv);
}

DeviceServer::DeviceServer( ServerSocket * serverSocket,
                            Socket * socket,
                            const std::vector<std::string> & devices ) :
    Server(serverSocket) {
    initialize();
    setSocket(socket);
    setDeviceIdentifiers(devices);
}

DeviceServer::~DeviceServer( void ) {
    join();
}

void DeviceServer::start( void ) {
    if( mListenThread == nullptr && mDispatchThread == nullptr ) {
        startListenThread();
        startDispatchThread();
    }
}

void DeviceServer::stop( void ) {
    if( mFlagRunning ) {
        logi("Stopping device server.");
        mFlagRunning = false;
        mSocket->closeConnection();
        getServerSocket()->stopListening();
    }
}

void DeviceServer::join( void ) {
    if( mListenThread != nullptr ) {
        mListenThread->join();
        delete mListenThread;
        mListenThread = nullptr;
    }
    if( mDispatchThread != nullptr ) {
        mDispatchThread->join();
        delete mDispatchThread;
        mDispatchThread = nullptr;
    }
}

void DeviceServer::update( void ) {
    // Do nothing.
}

void DeviceServer::update( void * argument ) {
    std::map<Session *,std::thread *>::iterator it;
    Session * session;

    // Checking the precondition.
    assert( argument != nullptr );

    session = static_cast<Session *>(argument);
    it = mSessions.find(session);
    if( it != mSessions.end() ) {
        mInactiveThreads.push_back(it->second);
        mMutexSessions.lock();
        mSessions.erase(it);
        mMutexSessions.unlock();
    }
}
<commit_msg>Fix possible bug.<commit_after>/**
 * A server which is responsible for interacting with devices.
 *
 * @date                    July 7, 2014
 * @author                    Joeri HERMANS
 * @version                    0.1
 *
 * Copyright 2013 Joeri HERMANS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// BEGIN Includes. ///////////////////////////////////////////////////

// System dependencies.
#include <arpa/inet.h>
#include <cassert>
#include <cstdio>
#include <iostream>

// Application dependencies.
#include <ias/server/device_server.h>
#include <ias/server/session/device_session.h>
#include <ias/logger/logger.h>

// END Includes. /////////////////////////////////////////////////////

inline void DeviceServer::initialize( void ) {
    mSocket = nullptr;
    mListenThread = nullptr;
    mDispatchThread = nullptr;
    mFlagRunning = true;
}

void DeviceServer::setSocket( Socket * socket ) {
    // Checking the precondition.
    assert( socket != nullptr && socket->isConnected() );

    mSocket = socket;
}

void DeviceServer::setDeviceIdentifiers( const std::vector<std::string> & i ) {
    mDeviceIdentifiers = i;
}

void DeviceServer::startListenThread( void ) {
    mListenThread = new std::thread([this](){
        ServerSocket * serverSocket;
        Session * session;
        Socket * socket;

        serverSocket = getServerSocket();
        while( mFlagRunning && mSocket->isConnected() ) {
            socket = serverSocket->acceptSocket(1);
            if( socket != nullptr ) {
                logi("Starting new device session.");
                session = new DeviceSession(socket,
                                            mSocket,
                                            &mConnectedDevices,
                                            &mDeviceIdentifiers);
                session->addObserver(this);
                mSessions[session] =
                    new std::thread([session]{
                        session->run();
                        session->notifyObservers(session);
                        delete session;
                        logi("Device session terminated.");
                    });
            }
            cleanupFinishingThreads();
        }
        signalSessions();
        mSocket->closeConnection();
        while( mSessions.size() > 0 ||
               mInactiveThreads.size() > 0 ) {
            signalSessions();
            cleanupFinishingThreads();
        }
    });
}

bool DeviceServer::readBytes( char * buffer , const unsigned int n ) {
    std::size_t bytesRead;
    std::size_t nBytes;
    Reader * reader;

    // Checking the precondition.
    assert( buffer != nullptr && n > 0 );

    if( !mSocket->isConnected() ) return ( false );

    reader = mSocket->getReader();
    bytesRead = 0;
    while( bytesRead != n ) {
        nBytes = reader->readBytes(buffer + bytesRead,n - bytesRead);
        if( nBytes == 0 )
            return ( false );
        bytesRead += nBytes;
    }

    return ( true );
}

void DeviceServer::dispatchCommand( void ) {
    std::uint8_t deviceLength;
    std::uint8_t identifierLength;
    std::uint8_t parameterLength;
    std::string message;

    if( mSocket->isConnected() ) {
        if( !readBytes(reinterpret_cast<char *>(&deviceLength),1) ) return;
        if( !readBytes(reinterpret_cast<char *>(&identifierLength),1) ) return;
        if( !readBytes(reinterpret_cast<char *>(&parameterLength),1) ) return;
        char deviceIdentifier[deviceLength + 1];
        char identifier[identifierLength + 1];
        char parameter[parameterLength + 1];
        if( !readBytes(deviceIdentifier,deviceLength) ) return;
        if( !readBytes(identifier,identifierLength) ) return;
        if( parameterLength > 0 && !readBytes(parameter,parameterLength) )
            return;
        deviceIdentifier[deviceLength] = 0;
        identifier[identifierLength] = 0;
        parameter[parameterLength] = 0;
        // Format the message
        message += 0x01;
        message += identifierLength;
        message += parameterLength;
        message.append(identifier);
        message.append(parameter);
        mConnectedDevices.dispatch(deviceIdentifier,message);
    } else {
        stop();
    }
}

void DeviceServer::startDispatchThread( void ) {
    mDispatchThread = new std::thread([this](){
        std::size_t nBytes;
        std::uint8_t type;
        Reader * reader;
        bool heartbeatSend = false;

        setServerTimeouts();
        reader = mSocket->getReader();
        while( mFlagRunning && mSocket->isConnected() ) {
            type = 0xff;
            reader->lock();
            nBytes = reader->readByte(reinterpret_cast<char *>(&type));
            reader->unlock();
            if( nBytes == 0 ) {
                if( !serverHeartbeat() || heartbeatSend )
                    stop();
                else
                    heartbeatSend = true;
                continue;
            }
            switch(type) {
            case 0x00:
                if( !heartbeatSend )
                    serverHeartbeat();
                break;
            case 0x01:
                dispatchCommand();
                break;
            default:
                mFlagRunning = false;
                break;
            }
            heartbeatSend = false;
        }
        stop();
    });
}

void DeviceServer::signalSessions( void ) {
    std::map<Session *,std::thread *>::iterator it;

    mMutexSessions.lock();
    for( it = mSessions.begin() ; it != mSessions.end() ; ++it )
        it->first->stop();
    mMutexSessions.unlock();
}

void DeviceServer::cleanupFinishingThreads( void ) {
    std::thread * t;

    while( mInactiveThreads.size() > 0 ) {
        t = mInactiveThreads.front();
        if( t != nullptr ) {
            t->join();
            delete t;
        }
        mInactiveThreads.erase(mInactiveThreads.begin());
    }
}

bool DeviceServer::serverHeartbeat( void ) {
    static const std::int8_t beat = 0x00;
    Writer * writer;
    bool ok;

    writer = mSocket->getWriter();
    writer->lock();
    ok = (writer->writeBytes(reinterpret_cast<const char *>(&beat),1) == 1);
    writer->unlock();

    return ( ok );
}

void DeviceServer::setServerTimeouts( void ) {
    struct timeval tv;

    tv.tv_sec = 20;
    tv.tv_usec = 0;
    mSocket->setReceiveTimeout(tv);
}

DeviceServer::DeviceServer( ServerSocket * serverSocket,
                            Socket * socket,
                            const std::vector<std::string> & devices ) :
    Server(serverSocket) {
    initialize();
    setSocket(socket);
    setDeviceIdentifiers(devices);
}

DeviceServer::~DeviceServer( void ) {
    join();
}

void DeviceServer::start( void ) {
    if( mListenThread == nullptr && mDispatchThread == nullptr ) {
        startListenThread();
        startDispatchThread();
    }
}

void DeviceServer::stop( void ) {
    if( mFlagRunning ) {
        logi("Stopping device server.");
        mFlagRunning = false;
        mSocket->closeConnection();
        getServerSocket()->stopListening();
    }
}

void DeviceServer::join( void ) {
    if( mListenThread != nullptr ) {
        mListenThread->join();
        delete mListenThread;
        mListenThread = nullptr;
    }
    if( mDispatchThread != nullptr ) {
        mDispatchThread->join();
        delete mDispatchThread;
        mDispatchThread = nullptr;
    }
}

void DeviceServer::update( void ) {
    // Do nothing.
}

void DeviceServer::update( void * argument ) {
    std::map<Session *,std::thread *>::iterator it;
    Session * session;

    // Checking the precondition.
    assert( argument != nullptr );

    session = static_cast<Session *>(argument);
    it = mSessions.find(session);
    if( it != mSessions.end() ) {
        mInactiveThreads.push_back(it->second);
        mMutexSessions.lock();
        mSessions.erase(it);
        mMutexSessions.unlock();
    }
}
<|endoftext|>


<commit_before>
#include <QApplication>
#include <QPainter>
#include <propertyguizeug/PropertyDelegate.h>

namespace propertyguizeug {

PropertyDelegate::PropertyDelegate(QWidget * parent)
:   QStyledItemDelegate(parent)
{
}

PropertyDelegate::~PropertyDelegate()
{
}

void PropertyDelegate::paint(QPainter * painter,
   const QStyleOptionViewItem & option,
   const QModelIndex & index) const
{
    AbstractProperty * property = static_cast<AbstractProperty *>(index.internalPointer());

    if (property->isGroup())
        return QStyledItemDelegate::paint(painter, option, index);

    if (m_propertyPainter.drawValue(painter, option, *property))
        return;

    QStyleOptionViewItem myOption = option;
    QString text = QString::fromStdString(property->valueAsString());
    myOption.text = text;
    QStyledItemDelegate::paint(painter, myOption, index);
}

QWidget * PropertyDelegate::createEditor(QWidget * parent,
    const QStyleOptionViewItem & option, const QModelIndex & index) const
{
    AbstractProperty * property = static_cast<AbstractProperty *>(index.internalPointer());

    if (!property->isGroup())
        return const_cast<PropertyDelegate *>(this)->createEditorForProperty(parent, property);

    return QStyledItemDelegate::createEditor(parent, option, index);
}

void PropertyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
}

void PropertyDelegate::setModelData(QWidget * editor, QAbstractItemModel * model,
    const QModelIndex & index) const
{
}

void PropertyDelegate::updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option,
    const QModelIndex & index) const
{
    editor->setGeometry(option.rect);
}

QSize PropertyDelegate::sizeHint (const QStyleOptionViewItem & option,
    const QModelIndex & index) const
{
    return QSize(100, 30);
}

QWidget * PropertyDelegate::createEditorForProperty(QWidget * parent, AbstractProperty * property)
{
    QWidget * editor = m_editorFactory.createEditor(*property);
    editor->setParent(parent);
    return editor;
}

} // namespace
<commit_msg>refactor to guard clause<commit_after>
#include <QApplication>
#include <QPainter>
#include <propertyguizeug/PropertyDelegate.h>

namespace propertyguizeug {

PropertyDelegate::PropertyDelegate(QWidget * parent)
:   QStyledItemDelegate(parent)
{
}

PropertyDelegate::~PropertyDelegate()
{
}

void PropertyDelegate::paint(QPainter * painter,
   const QStyleOptionViewItem & option,
   const QModelIndex & index) const
{
    AbstractProperty * property = static_cast<AbstractProperty *>(index.internalPointer());

    if (property->isGroup())
        return QStyledItemDelegate::paint(painter, option, index);

    if (m_propertyPainter.drawValue(painter, option, *property))
        return;

    QStyleOptionViewItem myOption = option;
    QString text = QString::fromStdString(property->valueAsString());
    myOption.text = text;
    QStyledItemDelegate::paint(painter, myOption, index);
}

QWidget * PropertyDelegate::createEditor(QWidget * parent,
    const QStyleOptionViewItem & option, const QModelIndex & index) const
{
    AbstractProperty * property = static_cast<AbstractProperty *>(index.internalPointer());

    if (property->isGroup())
        return QStyledItemDelegate::createEditor(parent, option, index);

    return const_cast<PropertyDelegate *>(this)->createEditorForProperty(parent, property);
}

void PropertyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
}

void PropertyDelegate::setModelData(QWidget * editor, QAbstractItemModel * model,
    const QModelIndex & index) const
{
}

void PropertyDelegate::updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option,
    const QModelIndex & index) const
{
    editor->setGeometry(option.rect);
}

QSize PropertyDelegate::sizeHint (const QStyleOptionViewItem & option,
    const QModelIndex & index) const
{
    return QSize(100, 30);
}

QWidget * PropertyDelegate::createEditorForProperty(QWidget * parent, AbstractProperty * property)
{
    QWidget * editor = m_editorFactory.createEditor(*property);
    editor->setParent(parent);
    return editor;
}

} // namespace
<|endoftext|>


<commit_before>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

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

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

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "proximitylist_api.h"
#include "type/pb_converter.h"
#include "utils/paginate.h"
#include "ptreferential/ptreferential.h"

namespace navitia {
namespace proximitylist {
/**
 * se charge de remplir l'objet protocolbuffer autocomplete passé en paramètre
 *
 */
typedef std::tuple<nt::idx_t, nt::GeographicalCoord, nt::Type_e> t_result;
typedef std::pair<nt::idx_t, nt::GeographicalCoord> idx_coord;
static void make_pb(navitia::PbCreator& pb_creator,
                    const std::vector<t_result>& result,
                    uint32_t depth,
                    const nt::Data& data,
                    type::GeographicalCoord coord) {
    for (auto result_item : result) {
        pbnavitia::PtObject* place = pb_creator.add_places_nearby();
        auto idx = std::get<0>(result_item);
        auto coord_item = std::get<1>(result_item);
        auto type = std::get<2>(result_item);
        switch (type) {
            case nt::Type_e::StopArea:
                pb_creator.fill(data.pt_data->stop_areas[idx], place, depth);
                place->set_distance(coord.distance_to(coord_item));
                break;
            case nt::Type_e::StopPoint:
                pb_creator.fill(data.pt_data->stop_points[idx], place, depth);
                place->set_distance(coord.distance_to(coord_item));
                break;
            case nt::Type_e::POI:
                pb_creator.fill(data.geo_ref->pois[idx], place, depth);
                place->set_distance(coord.distance_to(coord_item));
                break;
            case nt::Type_e::Address: {
                const auto& way_coord = navitia::WayCoord(data.geo_ref->ways[idx], coord,
                                                          data.geo_ref->ways[idx]->nearest_number(coord).first);
                pb_creator.fill(&way_coord, place, depth);
                place->set_distance(coord.distance_to(coord_item));
                break;
            }
            default:
                break;
        }
    }
}

static void sort_cut(vector_idx_coord& list, const size_t end_pagination, const nt::GeographicalCoord& coord) {
    const double coslat = ::cos(coord.lat() * nt::GeographicalCoord::N_DEG_TO_RAD);
    const auto nb_sort = std::min(list.size(), end_pagination);
    std::partial_sort(list.begin(), list.begin() + nb_sort, list.end(), [&](const idx_coord& a, const idx_coord& b) {
        const auto sq_dist_a = coord.approx_sqr_distance(a.second, coslat);
        const auto sq_dist_b = coord.approx_sqr_distance(b.second, coslat);
        return sq_dist_a < sq_dist_b;
    });
    list.resize(nb_sort);
}

void find(navitia::PbCreator& pb_creator,
          const type::GeographicalCoord& coord,
          const double distance,
          const std::vector<nt::Type_e>& types,
          const std::string& filter,
          const uint32_t depth,
          const uint32_t count,
          const uint32_t start_page,
          const type::Data& data) {
    int total_result = 0;
    std::vector<t_result> result;
    auto end_pagination = (start_page + 1) * count;
    for (nt::Type_e type : types) {
        if (type == nt::Type_e::Address) {
            // for addresses we use the street network
            try {
                auto nb_w = pb_creator.data->geo_ref->nearest_addr(coord);
                // we'll regenerate the good number in make_pb
                result.push_back(t_result(nb_w.second->idx, coord, type));
                ++total_result;
            } catch (const proximitylist::NotFound&) {
            }
            continue;
        }

        vector_idx_coord list;
        type::Indexes indexes;
        if (!filter.empty()) {
            try {
                indexes = ptref::make_query(type, filter, *pb_creator.data);
            } catch (const ptref::parsing_error& parse_error) {
                pb_creator.fill_pb_error(pbnavitia::Error::unable_to_parse,
                                         "Problem while parsing the query:" + parse_error.more);
                return;
            } catch (const ptref::ptref_error& pt_error) {
                pb_creator.fill_pb_error(pbnavitia::Error::bad_filter, "ptref : " + pt_error.more);
                return;
            }
        }
        switch (type) {
            case nt::Type_e::StopArea:
                list = pb_creator.data->pt_data->stop_area_proximity_list.find_within(coord, distance, count);
                break;
            case nt::Type_e::StopPoint:
                list = pb_creator.data->pt_data->stop_point_proximity_list.find_within(coord, distance, count);
                break;
            case nt::Type_e::POI:
                list = pb_creator.data->geo_ref->poi_proximity_list.find_within(coord, distance, count);
                break;
            default:
                break;
        }

        vector_idx_coord final_list;
        if (filter.empty()) {
            final_list = list;
        } else {
            // We find the intersection between indexes and list
            // we sort the proximity list on the indexes
            auto comp = [](idx_coord a, idx_coord b) { return a.first < b.first; };
            std::sort(list.begin(), list.end(), comp);

            for (auto idx : indexes) {
                auto it = std::lower_bound(list.begin(), list.end(), std::make_pair(idx, nt::GeographicalCoord()),
                                           comp);  // we create a mock pair and only compare the first elt
                if (it != list.end() && (*it).first == idx) {
                    final_list.push_back(*it);
                    if (final_list.size() == list.size()) {
                        // small speedup, if all geographical elt have been added we can stop
                        //(since the indexes list might be way bigger than the proximity list)
                        break;
                    }
                }
            }
        }
        total_result += final_list.size();
        sort_cut(final_list, end_pagination, coord);
        for (auto idx_coord : final_list) {
            result.push_back(t_result(idx_coord.first, idx_coord.second, type));
        }
    }
    auto nb_sort = (result.size() < end_pagination) ? result.size() : end_pagination;
    std::partial_sort(result.begin(), result.begin() + nb_sort, result.end(),
                      [coord](t_result t1, t_result t2) -> bool {
                          auto a = std::get<1>(t1);
                          auto b = std::get<1>(t2);
                          return coord.distance_to(a) < coord.distance_to(b);
                      });
    result = paginate(result, count, start_page);
    make_pb(pb_creator, result, depth, data, coord);
    pb_creator.make_paginate(total_result, start_page, count, result.size());
}
}  // namespace proximitylist
}  // namespace navitia
<commit_msg>fix count in places_nearby<commit_after>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

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

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

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "proximitylist_api.h"
#include "type/pb_converter.h"
#include "utils/paginate.h"
#include "ptreferential/ptreferential.h"

namespace navitia {
namespace proximitylist {
/**
 * se charge de remplir l'objet protocolbuffer autocomplete passé en paramètre
 *
 */
typedef std::tuple<nt::idx_t, nt::GeographicalCoord, nt::Type_e> t_result;
typedef std::pair<nt::idx_t, nt::GeographicalCoord> idx_coord;
static void make_pb(navitia::PbCreator& pb_creator,
                    const std::vector<t_result>& result,
                    uint32_t depth,
                    const nt::Data& data,
                    type::GeographicalCoord coord) {
    for (auto result_item : result) {
        pbnavitia::PtObject* place = pb_creator.add_places_nearby();
        auto idx = std::get<0>(result_item);
        auto coord_item = std::get<1>(result_item);
        auto type = std::get<2>(result_item);
        switch (type) {
            case nt::Type_e::StopArea:
                pb_creator.fill(data.pt_data->stop_areas[idx], place, depth);
                place->set_distance(coord.distance_to(coord_item));
                break;
            case nt::Type_e::StopPoint:
                pb_creator.fill(data.pt_data->stop_points[idx], place, depth);
                place->set_distance(coord.distance_to(coord_item));
                break;
            case nt::Type_e::POI:
                pb_creator.fill(data.geo_ref->pois[idx], place, depth);
                place->set_distance(coord.distance_to(coord_item));
                break;
            case nt::Type_e::Address: {
                const auto& way_coord = navitia::WayCoord(data.geo_ref->ways[idx], coord,
                                                          data.geo_ref->ways[idx]->nearest_number(coord).first);
                pb_creator.fill(&way_coord, place, depth);
                place->set_distance(coord.distance_to(coord_item));
                break;
            }
            default:
                break;
        }
    }
}

static void sort_cut(vector_idx_coord& list, const size_t end_pagination, const nt::GeographicalCoord& coord) {
    const double coslat = ::cos(coord.lat() * nt::GeographicalCoord::N_DEG_TO_RAD);
    const auto nb_sort = std::min(list.size(), end_pagination);
    std::partial_sort(list.begin(), list.begin() + nb_sort, list.end(), [&](const idx_coord& a, const idx_coord& b) {
        const auto sq_dist_a = coord.approx_sqr_distance(a.second, coslat);
        const auto sq_dist_b = coord.approx_sqr_distance(b.second, coslat);
        return sq_dist_a < sq_dist_b;
    });
    list.resize(nb_sort);
}

void find(navitia::PbCreator& pb_creator,
          const type::GeographicalCoord& coord,
          const double distance,
          const std::vector<nt::Type_e>& types,
          const std::string& filter,
          const uint32_t depth,
          const uint32_t count,
          const uint32_t start_page,
          const type::Data& data) {
    int total_result = 0;
    std::vector<t_result> result;
    auto end_pagination = (start_page + 1) * count;
    for (nt::Type_e type : types) {
        if (type == nt::Type_e::Address) {
            // for addresses we use the street network
            try {
                auto nb_w = pb_creator.data->geo_ref->nearest_addr(coord);
                // we'll regenerate the good number in make_pb
                result.push_back(t_result(nb_w.second->idx, coord, type));
                ++total_result;
            } catch (const proximitylist::NotFound&) {
            }
            continue;
        }

        vector_idx_coord list;
        type::Indexes indexes;
        int search_count = count;
        if (!filter.empty()) {
            try {
                indexes = ptref::make_query(type, filter, *pb_creator.data);
            } catch (const ptref::parsing_error& parse_error) {
                pb_creator.fill_pb_error(pbnavitia::Error::unable_to_parse,
                                         "Problem while parsing the query:" + parse_error.more);
                return;
            } catch (const ptref::ptref_error& pt_error) {
                pb_creator.fill_pb_error(pbnavitia::Error::bad_filter, "ptref : " + pt_error.more);
                return;
            }
            // We have to find all objects within distance, then apply the filter
            search_count = -1;
        }
        switch (type) {
            case nt::Type_e::StopArea:
                list = pb_creator.data->pt_data->stop_area_proximity_list.find_within(coord, distance, search_count);
                break;
            case nt::Type_e::StopPoint:
                list = pb_creator.data->pt_data->stop_point_proximity_list.find_within(coord, distance, search_count);
                break;
            case nt::Type_e::POI:
                list = pb_creator.data->geo_ref->poi_proximity_list.find_within(coord, distance, search_count);
                break;
            default:
                break;
        }

        vector_idx_coord final_list;
        if (filter.empty()) {
            final_list = list;
        } else {
            // We find the intersection between indexes and list
            // we sort the proximity list on the indexes
            auto comp = [](idx_coord a, idx_coord b) { return a.first < b.first; };
            std::sort(list.begin(), list.end(), comp);
            size_t added = 0;

            for (auto idx : indexes) {
                auto it = std::lower_bound(list.begin(), list.end(), std::make_pair(idx, nt::GeographicalCoord()),
                                           comp);  // we create a mock pair and only compare the first elt
                if (it != list.end() && (*it).first == idx) {
                    final_list.push_back(*it);
                    if (final_list.size() == list.size() || ++added == count) {
                        // small speedup, if all geographical elt have been added we can stop
                        //(since the indexes list might be way bigger than the proximity list)
                        break;
                    }
                }
            }
        }
        total_result += final_list.size();
        sort_cut(final_list, end_pagination, coord);
        for (auto idx_coord : final_list) {
            result.push_back(t_result(idx_coord.first, idx_coord.second, type));
        }
    }
    auto nb_sort = (result.size() < end_pagination) ? result.size() : end_pagination;
    std::partial_sort(result.begin(), result.begin() + nb_sort, result.end(),
                      [coord](t_result t1, t_result t2) -> bool {
                          auto a = std::get<1>(t1);
                          auto b = std::get<1>(t2);
                          return coord.distance_to(a) < coord.distance_to(b);
                      });
    result = paginate(result, count, start_page);
    make_pb(pb_creator, result, depth, data, coord);
    pb_creator.make_paginate(total_result, start_page, count, result.size());
}
}  // namespace proximitylist
}  // namespace navitia
<|endoftext|>


<commit_before>#pragma once

#ifndef RAZ_STRUTILS_HPP
#define RAZ_STRUTILS_HPP

#include <algorithm>
#include <cctype>
#include <string>

namespace Raz {

namespace StrUtils {

inline char toLowercase(char& character) {
  character = static_cast<char>(std::tolower(static_cast<unsigned char>(character)));
  return character;
}

inline std::string& toLowercase(std::string& text) {
  std::transform(text.begin(), text.end(), text.begin(), ::tolower);
  return text;
}

inline char toUppercase(char& character) {
  character = static_cast<char>(std::toupper(static_cast<unsigned char>(character)));
  return character;
}

inline std::string& toUppercase(std::string& text) {
  std::transform(text.begin(), text.end(), text.begin(), ::toupper);
  return text;
}

inline char toLowercaseCopy(char character) {
  toLowercase(character);
  return character;
}

inline std::string toLowercaseCopy(std::string text) {
  toLowercase(text);
  return text;
}

inline char toUppercaseCopy(char character) {
  toUppercase(character);
  return character;
}

inline std::string toUppercaseCopy(std::string text) {
  toUppercase(text);
  return text;
}

inline std::string& trimLeft(std::string& text) {
  text.erase(text.begin(), std::find_if(text.begin(), text.end(), [] (int c) {
    return !std::isspace(c);
  }));
  return text;
}

inline std::string& trimRight(std::string& text) {
  text.erase(std::find_if(text.rbegin(), text.rend(), [] (int c) {
    return !std::isspace(c);
  }).base(), text.end());
  return text;
}

inline std::string& trim(std::string& text) {
  trimLeft(text);
  trimRight(text);
  return text;
}

inline std::string trimLeftCopy(std::string text) {
  trimLeft(text);
  return text;
}

inline std::string trimRightCopy(std::string text) {
  trimRight(text);
  return text;
}

inline std::string trimCopy(std::string text) {
  trim(text);
  return text;
}

inline std::vector<std::string> split(std::string inputStr, char delimiter) {
  trimRight(inputStr);

  std::vector<std::string> parts {};

  while (!inputStr.empty()) {
    const std::size_t delimPos = inputStr.find_first_of(delimiter);

    if (delimPos > inputStr.size()) {
      parts.push_back(inputStr);
      break;
    }

    parts.push_back(inputStr.substr(0, delimPos));
    trimRight(parts.back());

    inputStr.erase(0, delimPos + 1);
    trimLeft(inputStr);
  }

  return parts;
}

} // namespace StrUtils

} // namespace Raz

#endif // RAZ_STRUTILS_HPP
<commit_msg>[Update] Added documentation for StrUtils functions [Update] Renamed StrUtils::split() string param for consistency<commit_after>#pragma once

#ifndef RAZ_STRUTILS_HPP
#define RAZ_STRUTILS_HPP

#include <algorithm>
#include <cctype>
#include <string>

namespace Raz {

namespace StrUtils {

/// Transforms in-place a character to lowercase.
/// \param character Character to be transformed.
/// \return Lowercase character.
inline char toLowercase(char& character) {
  character = static_cast<char>(std::tolower(static_cast<unsigned char>(character)));
  return character;
}

/// Transforms in-place a string to lowercase.
/// \param text String to be transformed.
/// \return Reference to the lowercase string.
inline std::string& toLowercase(std::string& text) {
  std::transform(text.begin(), text.end(), text.begin(), ::tolower);
  return text;
}

/// Transforms in-place a character to uppercase.
/// \param character Character to be transformed.
/// \return Uppercase character.
inline char toUppercase(char& character) {
  character = static_cast<char>(std::toupper(static_cast<unsigned char>(character)));
  return character;
}

/// Transforms in-place a string to uppercase.
/// \param text String to be transformed.
/// \return Reference to the uppercase string.
inline std::string& toUppercase(std::string& text) {
  std::transform(text.begin(), text.end(), text.begin(), ::toupper);
  return text;
}

/// Transforms a character to lowercase without modifying the input.
/// \param character Character to be transformed.
/// \return Lowercase character.
inline char toLowercaseCopy(char character) {
  toLowercase(character);
  return character;
}

/// Transforms a string to lowercase without modifying the input.
/// \param text String to be transformed.
/// \return Lowercase string copy.
inline std::string toLowercaseCopy(std::string text) {
  toLowercase(text);
  return text;
}

/// Transforms a character to uppercase without modifying the input.
/// \param character Character to be transformed.
/// \return Uppercase character.
inline char toUppercaseCopy(char character) {
  toUppercase(character);
  return character;
}

/// Transforms a string to uppercase without modifying the input.
/// \param text String to be transformed.
/// \return Uppercase string copy.
inline std::string toUppercaseCopy(std::string text) {
  toUppercase(text);
  return text;
}

/// Removes spaces in-place at the start of a string.
/// \param text String to be trimmed.
/// \return Reference to the trimmed string.
inline std::string& trimLeft(std::string& text) {
  text.erase(text.begin(), std::find_if(text.begin(), text.end(), [] (int c) {
    return !std::isspace(c);
  }));
  return text;
}

/// Removes spaces in-place at the end of a string.
/// \param text String to be trimmed.
/// \return Reference to the trimmed string.
inline std::string& trimRight(std::string& text) {
  text.erase(std::find_if(text.rbegin(), text.rend(), [] (int c) {
    return !std::isspace(c);
  }).base(), text.end());
  return text;
}

/// Removes spaces in-place on both ends of a string.
/// \param text String to be trimmed.
/// \return Reference to the trimmed string.
inline std::string& trim(std::string& text) {
  trimLeft(text);
  trimRight(text);
  return text;
}

/// Removes spaces at the start of a string without modifying the input.
/// \param text String to be trimmed.
/// \return Trimmed string copy.
inline std::string trimLeftCopy(std::string text) {
  trimLeft(text);
  return text;
}

/// Removes spaces at the end of a string without modifying the input.
/// \param text String to be trimmed.
/// \return Trimmed string copy.
inline std::string trimRightCopy(std::string text) {
  trimRight(text);
  return text;
}

/// Removes spaces on both ends of a string without modifying the input.
/// \param text String to be trimmed.
/// \return Trimmed string copy.
inline std::string trimCopy(std::string text) {
  trim(text);
  return text;
}

/// Splits a string with a given delimiter.
/// \param text String to be splitted.
/// \param delimiter Character used to split into parts.
/// \return Parts of the splitted string.
inline std::vector<std::string> split(std::string text, char delimiter) {
  trimRight(text);

  std::vector<std::string> parts {};

  while (!text.empty()) {
    const std::size_t delimPos = text.find_first_of(delimiter);

    if (delimPos > text.size()) {
      parts.push_back(text);
      break;
    }

    parts.push_back(text.substr(0, delimPos));
    trimRight(parts.back());

    text.erase(0, delimPos + 1);
    trimLeft(text);
  }

  return parts;
}

} // namespace StrUtils

} // namespace Raz

#endif // RAZ_STRUTILS_HPP
<|endoftext|>