<commit_before>/* This file is part of VoltDB.
 * Copyright (C) 2008-2010 VoltDB Inc.
 *
 * VoltDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VoltDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "storage/TupleBlock.h"
#include "storage/table.h"
#include <sys/mman.h>
#include <errno.h>
#include "common/ThreadLocalPool.h"

namespace voltdb {

volatile int tupleBlocksAllocated = 0;

TupleBlock::TupleBlock(Table *table, TBBucketPtr bucket) :
        m_references(0),
        m_table(table),
        m_storage(NULL),
        m_tupleLength(table->m_tupleLength),
        m_tuplesPerBlock(table->m_tuplesPerBlock),
        m_activeTuples(0),
        m_nextFreeTuple(0),
        m_lastCompactionOffset(0),
        m_tuplesPerBlockDivNumBuckets(m_tuplesPerBlock / static_cast<double>(TUPLE_BLOCK_NUM_BUCKETS)),
        m_bucketIndex(0),
        m_bucket(bucket) {
#ifdef MEMCHECK
    m_storage = new char[table->m_tableAllocationSize];
#else
#ifdef USE_MMAP
    m_storage = static_cast<char*>(::mmap( 0, table->m_tableAllocationSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0 ));
    if (m_storage == MAP_FAILED) {
        std::cout << strerror( errno ) << std::endl;
        throwFatalException("Failed mmap");
    }
#else
    m_storage = static_cast<char*>(ThreadLocalPool::getExact(m_table->m_tableAllocationSize)->malloc());
#endif
#endif
    tupleBlocksAllocated++;
}

TupleBlock::~TupleBlock() {
    /*
      tupleBlocksAllocated--;
      std::cout << "Destructing tuple block " << static_cast<void*>(this)
                << " with " << tupleBlocksAllocated << " left " << std::endl;
    */
#ifdef MEMCHECK
    delete []m_storage;
#else
#ifdef USE_MMAP
    if (::munmap( m_storage, m_table->m_tableAllocationSize) != 0) {
        std::cout << strerror( errno ) << std::endl;
        throwFatalException("Failed munmap");
    }
#else
    ThreadLocalPool::getExact(m_table->m_tableAllocationSize)->free(m_storage);
#endif
#endif
}

std::pair<int, int> TupleBlock::merge(Table *table, TBPtr source) {
    assert(source != this);
    /*
      std::cout << "Attempting to merge " << static_cast<void*> (this)
                << "(" << m_activeTuples << ") with " << static_cast<void*>(source.get())
                << "(" << source->m_activeTuples << ")";
      std::cout << " source last compaction offset is " << source->lastCompactionOffset()
                << " and active tuple count is " << source->m_activeTuples << std::endl;
    */

    uint32_t m_nextTupleInSourceOffset = source->lastCompactionOffset();
    int sourceTuplesPendingDeleteOnUndoRelease = 0;
    while (hasFreeTuples() && !source->isEmpty()) {
        TableTuple sourceTuple(table->schema());
        TableTuple destinationTuple(table->schema());

        bool foundSourceTuple = false;
        //Iterate further into the block looking for active tuples
        //Stop when running into the unused tuple boundry
        while (m_nextTupleInSourceOffset < source->unusedTupleBoundry()) {
            sourceTuple.move(&source->address()[m_tupleLength * m_nextTupleInSourceOffset]);
            m_nextTupleInSourceOffset++;
            if (sourceTuple.isActive()) {
                foundSourceTuple = true;
                break;
            }
        }

        if (!foundSourceTuple) {
           //The block isn't empty, but there are no more active tuples.
           //Some of the tuples that make it register as not empty must have been
           //pending delete and those aren't mergable
            assert(sourceTuplesPendingDeleteOnUndoRelease);
            break;
        }

        //Can't move a tuple with a pending undo action, it would invalidate the pointer
        //Keep a count so that the block can be notified of the number
        //of tuples pending delete on undo release when calculating the correct bucket
        //index. If all the active tuples are pending delete on undo release the block
        //is effectively empty and shouldn't be considered for merge ops.
        //It will be completely discarded once the undo log releases the block.
        if (sourceTuple.isPendingDeleteOnUndoRelease()) {
            sourceTuplesPendingDeleteOnUndoRelease++;
            continue;
        }

        destinationTuple.move(nextFreeTuple().first);
        table->swapTuples( sourceTuple, destinationTuple);
        source->freeTuple(sourceTuple.address());
    }
    source->lastCompactionOffset(m_nextTupleInSourceOffset);

    int newBucketIndex = calculateBucketIndex();
    if (newBucketIndex != m_bucketIndex) {
        m_bucketIndex = newBucketIndex;
        //std::cout << "Merged " << static_cast<void*> (this) << "(" << m_activeTuples << ") with " << static_cast<void*>(source.get())  << "(" << source->m_activeTuples << ")";
        //std::cout << " found " << sourceTuplesPendingDeleteOnUndoRelease << " tuples pending delete on undo release "<< std::endl;
        return std::pair<int, int>(newBucketIndex, source->calculateBucketIndex(sourceTuplesPendingDeleteOnUndoRelease));
    } else {
        //std::cout << "Merged " << static_cast<void*> (this) << "(" << m_activeTuples << ") with " << static_cast<void*>(source.get()) << "(" << source->m_activeTuples << ")";
        //std::cout << " found " << sourceTuplesPendingDeleteOnUndoRelease << " tuples pending delete on undo release "<< std::endl;
        return std::pair<int, int>( -1, source->calculateBucketIndex(sourceTuplesPendingDeleteOnUndoRelease));
    }
}
}

<commit_msg>Have tuple blocks (which support compaction) use new and delete instead of the new pooling functionality. This should make the RSS responsive to deletes and it is the direction we are heading torwards with large allocations and compaction to return them.<commit_after>/* This file is part of VoltDB.
 * Copyright (C) 2008-2010 VoltDB Inc.
 *
 * VoltDB is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VoltDB is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VoltDB.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "storage/TupleBlock.h"
#include "storage/table.h"
#include <sys/mman.h>
#include <errno.h>
#include "common/ThreadLocalPool.h"

namespace voltdb {

volatile int tupleBlocksAllocated = 0;

TupleBlock::TupleBlock(Table *table, TBBucketPtr bucket) :
        m_references(0),
        m_table(table),
        m_storage(NULL),
        m_tupleLength(table->m_tupleLength),
        m_tuplesPerBlock(table->m_tuplesPerBlock),
        m_activeTuples(0),
        m_nextFreeTuple(0),
        m_lastCompactionOffset(0),
        m_tuplesPerBlockDivNumBuckets(m_tuplesPerBlock / static_cast<double>(TUPLE_BLOCK_NUM_BUCKETS)),
        m_bucketIndex(0),
        m_bucket(bucket) {
#ifdef MEMCHECK
    m_storage = new char[table->m_tableAllocationSize];
#else
#ifdef USE_MMAP
    m_storage = static_cast<char*>(::mmap( 0, table->m_tableAllocationSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0 ));
    if (m_storage == MAP_FAILED) {
        std::cout << strerror( errno ) << std::endl;
        throwFatalException("Failed mmap");
    }
#else
    //m_storage = static_cast<char*>(ThreadLocalPool::getExact(m_table->m_tableAllocationSize)->malloc());
    m_storage = new char[table->m_tableAllocationSize];
#endif
#endif
    tupleBlocksAllocated++;
}

TupleBlock::~TupleBlock() {
    /*
      tupleBlocksAllocated--;
      std::cout << "Destructing tuple block " << static_cast<void*>(this)
                << " with " << tupleBlocksAllocated << " left " << std::endl;
    */
#ifdef MEMCHECK
    delete []m_storage;
#else
#ifdef USE_MMAP
    if (::munmap( m_storage, m_table->m_tableAllocationSize) != 0) {
        std::cout << strerror( errno ) << std::endl;
        throwFatalException("Failed munmap");
    }
#else
    delete []m_storage;
#endif
#endif
}

std::pair<int, int> TupleBlock::merge(Table *table, TBPtr source) {
    assert(source != this);
    /*
      std::cout << "Attempting to merge " << static_cast<void*> (this)
                << "(" << m_activeTuples << ") with " << static_cast<void*>(source.get())
                << "(" << source->m_activeTuples << ")";
      std::cout << " source last compaction offset is " << source->lastCompactionOffset()
                << " and active tuple count is " << source->m_activeTuples << std::endl;
    */

    uint32_t m_nextTupleInSourceOffset = source->lastCompactionOffset();
    int sourceTuplesPendingDeleteOnUndoRelease = 0;
    while (hasFreeTuples() && !source->isEmpty()) {
        TableTuple sourceTuple(table->schema());
        TableTuple destinationTuple(table->schema());

        bool foundSourceTuple = false;
        //Iterate further into the block looking for active tuples
        //Stop when running into the unused tuple boundry
        while (m_nextTupleInSourceOffset < source->unusedTupleBoundry()) {
            sourceTuple.move(&source->address()[m_tupleLength * m_nextTupleInSourceOffset]);
            m_nextTupleInSourceOffset++;
            if (sourceTuple.isActive()) {
                foundSourceTuple = true;
                break;
            }
        }

        if (!foundSourceTuple) {
           //The block isn't empty, but there are no more active tuples.
           //Some of the tuples that make it register as not empty must have been
           //pending delete and those aren't mergable
            assert(sourceTuplesPendingDeleteOnUndoRelease);
            break;
        }

        //Can't move a tuple with a pending undo action, it would invalidate the pointer
        //Keep a count so that the block can be notified of the number
        //of tuples pending delete on undo release when calculating the correct bucket
        //index. If all the active tuples are pending delete on undo release the block
        //is effectively empty and shouldn't be considered for merge ops.
        //It will be completely discarded once the undo log releases the block.
        if (sourceTuple.isPendingDeleteOnUndoRelease()) {
            sourceTuplesPendingDeleteOnUndoRelease++;
            continue;
        }

        destinationTuple.move(nextFreeTuple().first);
        table->swapTuples( sourceTuple, destinationTuple);
        source->freeTuple(sourceTuple.address());
    }
    source->lastCompactionOffset(m_nextTupleInSourceOffset);

    int newBucketIndex = calculateBucketIndex();
    if (newBucketIndex != m_bucketIndex) {
        m_bucketIndex = newBucketIndex;
        //std::cout << "Merged " << static_cast<void*> (this) << "(" << m_activeTuples << ") with " << static_cast<void*>(source.get())  << "(" << source->m_activeTuples << ")";
        //std::cout << " found " << sourceTuplesPendingDeleteOnUndoRelease << " tuples pending delete on undo release "<< std::endl;
        return std::pair<int, int>(newBucketIndex, source->calculateBucketIndex(sourceTuplesPendingDeleteOnUndoRelease));
    } else {
        //std::cout << "Merged " << static_cast<void*> (this) << "(" << m_activeTuples << ") with " << static_cast<void*>(source.get()) << "(" << source->m_activeTuples << ")";
        //std::cout << " found " << sourceTuplesPendingDeleteOnUndoRelease << " tuples pending delete on undo release "<< std::endl;
        return std::pair<int, int>( -1, source->calculateBucketIndex(sourceTuplesPendingDeleteOnUndoRelease));
    }
}
}

<|endoftext|>


<commit_before>#include <efsw/FileWatcherWin32.hpp>
#include <efsw/FileSystem.hpp>
#include <efsw/System.hpp>

#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32

namespace efsw
{

FileWatcherWin32::FileWatcherWin32( FileWatcher * parent ) :
	FileWatcherImpl( parent ),
	mLastWatchID(0),
	mThread( NULL )
{
	mInitOK = true;
}

FileWatcherWin32::~FileWatcherWin32()
{
	WatchVector::iterator iter = mWatches.begin();

	for(; iter != mWatches.end(); ++iter)
	{
		DestroyWatch((*iter));
	}

	mHandles.clear();
	mWatches.clear();

	mInitOK = false;

	efSAFE_DELETE( mThread );
}

WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive)
{
	std::string dir( directory );

	FileInfo fi( dir );

	if ( !fi.isDirectory() )
	{
		return Errors::Log::createLastError( Errors::FileNotFound, dir );
	}
	else if ( !fi.isReadable() )
	{
		return Errors::Log::createLastError( Errors::FileNotReadable, dir );
	}

	FileSystem::dirAddSlashAtEnd( dir );

	WatchID watchid = ++mLastWatchID;

	WatcherStructWin32 * watch = CreateWatch( dir.c_str(), recursive,	FILE_NOTIFY_CHANGE_CREATION |
																			FILE_NOTIFY_CHANGE_SIZE |
																			FILE_NOTIFY_CHANGE_FILE_NAME |
																			FILE_NOTIFY_CHANGE_DIR_NAME
	);

	if( NULL == watch )
	{
		return Errors::Log::createLastError( Errors::FileNotFound, dir );
	}

	if ( pathInWatches( dir ) )
	{
		return Errors::Log::createLastError( Errors::FileRepeated, dir );
	}

	// Add the handle to the handles vector
	watch->Watch->ID = watchid;
	watch->Watch->Watch = this;
	watch->Watch->Listener = watcher;
	watch->Watch->DirName = new char[dir.length()+1];
	strcpy(watch->Watch->DirName, dir.c_str());

	mWatchesLock.lock();
	mHandles.push_back( watch->Watch->DirHandle );
	mWatches.push_back( watch );
	mWatchesLock.unlock();

	return watchid;
}

void FileWatcherWin32::removeWatch(const std::string& directory)
{
	mWatchesLock.lock();

	WatchVector::iterator iter = mWatches.begin();

	for(; iter != mWatches.end(); ++iter)
	{
		if(directory == (*iter)->Watch->DirName)
		{
			removeWatch((*iter)->Watch->ID);
			return;
		}
	}

	mWatchesLock.unlock();
}

void FileWatcherWin32::removeWatch(WatchID watchid)
{
	mWatchesLock.lock();

	WatchVector::iterator iter = mWatches.begin();

	WatcherStructWin32* watch = NULL;

	for(; iter != mWatches.end(); ++iter)
	{
		// Find the watch ID
		if ( (*iter)->Watch->ID == watchid )
		{
			watch	= (*iter);

			mWatches.erase( iter );

			// Remove handle from the handle vector
			HandleVector::iterator it = mHandles.begin();

			for ( ; it != mHandles.end(); it++ )
			{
				if ( watch->Watch->DirHandle == (*it) )
				{
					mHandles.erase( it );
					break;
				}
			}

			DestroyWatch(watch);

			break;
		}
	}

	mWatchesLock.unlock();
}

void FileWatcherWin32::watch()
{
	if ( NULL == mThread )
	{
		mThread = new Thread( &FileWatcherWin32::run, this );
		mThread->launch();
	}
}

void FileWatcherWin32::run()
{
	if ( mHandles.empty() )
	{
		return;
	}

	do
	{
		DWORD wait_result = WaitForMultipleObjectsEx( mHandles.size(), &mHandles[0], FALSE, 1000, FALSE );

		switch ( wait_result )
		{
			case WAIT_ABANDONED_0:
			case WAIT_ABANDONED_0 + 1:
				//"Wait abandoned."
				break;
			case WAIT_TIMEOUT:
				break;
			case WAIT_FAILED:
				//"Wait failed."
				break;
			default:
			{
				mWatchesLock.lock();

				// Don't trust the result - multiple objects may be signalled during a single call.
				if ( wait_result >=  WAIT_OBJECT_0 && wait_result < WAIT_OBJECT_0 + mWatches.size() )
				{
					WatcherStructWin32 * watch = mWatches[ wait_result ];

					// First ensure that the handle is the same, this means that the watch was not removed.
					if ( mHandles[ wait_result ] == watch->Watch->DirHandle && HasOverlappedIoCompleted( &watch->Overlapped ) )
					{
						DWORD bytes;

						if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) )
						{
							WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped );
						}
						else
						{
							//"GetOverlappedResult failed."
						}
					}
				}
				else
				{
					//"Unknown return value from WaitForMultipleObjectsEx."
				}

				mWatchesLock.unlock();
			}
		}
	} while ( mInitOK );
}

void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename)
{
	Action fwAction;

	switch(action)
	{
	case FILE_ACTION_RENAMED_OLD_NAME:
		watch->OldFileName = filename;
		return;
	case FILE_ACTION_ADDED:
		fwAction = Actions::Add;
		break;
	case FILE_ACTION_RENAMED_NEW_NAME:
	{
		fwAction = Actions::Moved;

		std::string fpath( watch->Directory + filename );

		// Update the directory path
		if ( watch->Recursive && FileSystem::isDirectory( fpath ) )
		{
			// Update the new directory path
			std::string opath( watch->Directory + watch->OldFileName );
			FileSystem::dirAddSlashAtEnd( opath );
			FileSystem::dirAddSlashAtEnd( fpath );

			for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
			{
				if ( (*it)->Watch->Directory == opath )
				{
					(*it)->Watch->Directory = fpath;

					break;
				}
			}
		}

		watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction, watch->OldFileName);
		return;
	}
	case FILE_ACTION_REMOVED:
		fwAction = Actions::Delete;
		break;
	case FILE_ACTION_MODIFIED:
		fwAction = Actions::Modified;
		break;
	};

	watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction);
}

std::list<std::string> FileWatcherWin32::directories()
{
	std::list<std::string> dirs;

	mWatchesLock.lock();

	for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
	{
		dirs.push_back( std::string( (*it)->Watch->DirName ) );
	}

	mWatchesLock.unlock();

	return dirs;
}

bool FileWatcherWin32::pathInWatches( const std::string& path )
{
	for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
	{
		if ( (*it)->Watch->DirName == path )
		{
			return true;
		}
	}

	return false;
}

}

#endif
<commit_msg>Fixed issue #10. Thanks again Sepehr Taghdisian!<commit_after>#include <efsw/FileWatcherWin32.hpp>
#include <efsw/FileSystem.hpp>
#include <efsw/System.hpp>

#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32

namespace efsw
{

FileWatcherWin32::FileWatcherWin32( FileWatcher * parent ) :
	FileWatcherImpl( parent ),
	mLastWatchID(0),
	mThread( NULL )
{
	mInitOK = true;
}

FileWatcherWin32::~FileWatcherWin32()
{
	WatchVector::iterator iter = mWatches.begin();

	for(; iter != mWatches.end(); ++iter)
	{
		DestroyWatch((*iter));
	}

	mHandles.clear();
	mWatches.clear();

	mInitOK = false;

	efSAFE_DELETE( mThread );
}

WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive)
{
	std::string dir( directory );

	FileInfo fi( dir );

	if ( !fi.isDirectory() )
	{
		return Errors::Log::createLastError( Errors::FileNotFound, dir );
	}
	else if ( !fi.isReadable() )
	{
		return Errors::Log::createLastError( Errors::FileNotReadable, dir );
	}

	FileSystem::dirAddSlashAtEnd( dir );

	WatchID watchid = ++mLastWatchID;

	WatcherStructWin32 * watch = CreateWatch( dir.c_str(), recursive,		FILE_NOTIFY_CHANGE_CREATION |
																			FILE_NOTIFY_CHANGE_SIZE |
																			FILE_NOTIFY_CHANGE_FILE_NAME |
																			FILE_NOTIFY_CHANGE_DIR_NAME
	);

	if( NULL == watch )
	{
		return Errors::Log::createLastError( Errors::FileNotFound, dir );
	}

	if ( pathInWatches( dir ) )
	{
		return Errors::Log::createLastError( Errors::FileRepeated, dir );
	}

	// Add the handle to the handles vector
	watch->Watch->ID = watchid;
	watch->Watch->Watch = this;
	watch->Watch->Listener = watcher;
	watch->Watch->DirName = new char[dir.length()+1];
	strcpy(watch->Watch->DirName, dir.c_str());

	mWatchesLock.lock();
	mHandles.push_back( watch->Watch->DirHandle );
	mWatches.push_back( watch );
	mWatchesLock.unlock();

	return watchid;
}

void FileWatcherWin32::removeWatch(const std::string& directory)
{
	mWatchesLock.lock();

	WatchVector::iterator iter = mWatches.begin();

	for(; iter != mWatches.end(); ++iter)
	{
		if(directory == (*iter)->Watch->DirName)
		{
			removeWatch((*iter)->Watch->ID);
			return;
		}
	}

	mWatchesLock.unlock();
}

void FileWatcherWin32::removeWatch(WatchID watchid)
{
	mWatchesLock.lock();

	WatchVector::iterator iter = mWatches.begin();

	WatcherStructWin32* watch = NULL;

	for(; iter != mWatches.end(); ++iter)
	{
		// Find the watch ID
		if ( (*iter)->Watch->ID == watchid )
		{
			watch	= (*iter);

			mWatches.erase( iter );

			// Remove handle from the handle vector
			HandleVector::iterator it = mHandles.begin();

			for ( ; it != mHandles.end(); it++ )
			{
				if ( watch->Watch->DirHandle == (*it) )
				{
					mHandles.erase( it );
					break;
				}
			}

			DestroyWatch(watch);

			break;
		}
	}

	mWatchesLock.unlock();
}

void FileWatcherWin32::watch()
{
	if ( NULL == mThread )
	{
		mThread = new Thread( &FileWatcherWin32::run, this );
		mThread->launch();
	}
}

void FileWatcherWin32::run()
{
	if ( mHandles.empty() )
	{
		return;
	}

	do
	{
		if ( !mHandles.empty() )
		{
			DWORD wait_result = WaitForMultipleObjectsEx( mHandles.size(), &mHandles[0], FALSE, 1000, FALSE );

			switch ( wait_result )
			{
				case WAIT_ABANDONED_0:
				case WAIT_ABANDONED_0 + 1:
					//"Wait abandoned."
					break;
				case WAIT_TIMEOUT:
					break;
				case WAIT_FAILED:
					//"Wait failed."
					break;
				default:
				{
					mWatchesLock.lock();

					// Don't trust the result - multiple objects may be signalled during a single call.
					if ( wait_result >=  WAIT_OBJECT_0 && wait_result < WAIT_OBJECT_0 + mWatches.size() )
					{
						WatcherStructWin32 * watch = mWatches[ wait_result ];

						// First ensure that the handle is the same, this means that the watch was not removed.
						if ( mHandles[ wait_result ] == watch->Watch->DirHandle && HasOverlappedIoCompleted( &watch->Overlapped ) )
						{
							DWORD bytes;

							if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) )
							{
								WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped );
							}
							else
							{
								//"GetOverlappedResult failed."
							}
						}
					}
					else
					{
						//"Unknown return value from WaitForMultipleObjectsEx."
					}

					mWatchesLock.unlock();
				}
			}
		}
		else
		{
			// Wait for a new handle to be added
			System::sleep( 10 );
		}
	} while ( mInitOK );
}

void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename)
{
	Action fwAction;

	switch(action)
	{
	case FILE_ACTION_RENAMED_OLD_NAME:
		watch->OldFileName = filename;
		return;
	case FILE_ACTION_ADDED:
		fwAction = Actions::Add;
		break;
	case FILE_ACTION_RENAMED_NEW_NAME:
	{
		fwAction = Actions::Moved;

		std::string fpath( watch->Directory + filename );

		// Update the directory path
		if ( watch->Recursive && FileSystem::isDirectory( fpath ) )
		{
			// Update the new directory path
			std::string opath( watch->Directory + watch->OldFileName );
			FileSystem::dirAddSlashAtEnd( opath );
			FileSystem::dirAddSlashAtEnd( fpath );

			for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
			{
				if ( (*it)->Watch->Directory == opath )
				{
					(*it)->Watch->Directory = fpath;

					break;
				}
			}
		}

		watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction, watch->OldFileName);
		return;
	}
	case FILE_ACTION_REMOVED:
		fwAction = Actions::Delete;
		break;
	case FILE_ACTION_MODIFIED:
		fwAction = Actions::Modified;
		break;
	};

	watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction);
}

std::list<std::string> FileWatcherWin32::directories()
{
	std::list<std::string> dirs;

	mWatchesLock.lock();

	for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
	{
		dirs.push_back( std::string( (*it)->Watch->DirName ) );
	}

	mWatchesLock.unlock();

	return dirs;
}

bool FileWatcherWin32::pathInWatches( const std::string& path )
{
	for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
	{
		if ( (*it)->Watch->DirName == path )
		{
			return true;
		}
	}

	return false;
}

}

#endif
<|endoftext|>


<commit_before>/*****************************************************************************
 * vlcplugin.cpp: a VLC plugin for Mozilla
 *****************************************************************************
 * Copyright (C) 2002-2005 the VideoLAN team
 * $Id$
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
 *          Damien Fouilleul <damienf.fouilleul@laposte.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include "config.h"

#ifdef HAVE_MOZILLA_CONFIG_H
#   include <mozilla-config.h>
#endif

#include "vlcplugin.h"
#include "control/npovlc.h"
#include "control/npolibvlc.h"

/*****************************************************************************
 * VlcPlugin constructor and destructor
 *****************************************************************************/
VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) :
    i_npmode(mode),
    b_stream(0),
    b_autoplay(0),
    psz_target(NULL),
    libvlc_instance(NULL),
    scriptClass(NULL),
    p_browser(instance),
    psz_baseURL(NULL)
#if XP_WIN
    ,pf_wndproc(NULL)
#endif
#if XP_UNIX
    ,i_width((unsigned)-1)
    ,i_height((unsigned)-1)
#endif
{
    memset(&npwindow, 0, sizeof(NPWindow));
}

static int boolValue(const char *value) {
    return ( !strcmp(value, "1") ||
             !strcasecmp(value, "true") ||
             !strcasecmp(value, "yes") );
}

NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[])
{
    /* prepare VLC command line */
    char *ppsz_argv[32] =
    {
        "vlc",
        "-vv",
        "--no-stats",
        "--no-media-library",
        "--intf", "dummy",
    };
    int ppsz_argc = 6;

    /* locate VLC module path */
#ifdef XP_MACOSX
    ppsz_argv[ppsz_argc++] = "--plugin-path";
    ppsz_argv[ppsz_argc++] = "/Library/Internet Plug-Ins/VLC Plugin.plugin/"
                             "Contents/MacOS/modules";
#elif defined(XP_WIN)
    HKEY h_key;
    DWORD i_type, i_data = MAX_PATH + 1;
    char p_data[MAX_PATH + 1];
    if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC",
                      0, KEY_READ, &h_key ) == ERROR_SUCCESS )
    {
         if( RegQueryValueEx( h_key, "InstallDir", 0, &i_type,
                              (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS )
         {
             if( i_type == REG_SZ )
             {
                 strcat( p_data, "\\vlc" );
                 ppsz_argv[0] = p_data;
             }
         }
         RegCloseKey( h_key );
    }
    ppsz_argv[ppsz_argc++] = "--no-one-instance";
#if 0
    ppsz_argv[ppsz_argc++] = "--fast-mutex";
    ppsz_argv[ppsz_argc++] = "--win9x-cv-method=1";
#endif

#endif /* XP_MACOSX */

    const char *version = NULL;

    /* parse plugin arguments */
    for( int i = 0; i < argc ; i++ )
    {
        fprintf(stderr, "argn=%s, argv=%s\n", argn[i], argv[i]);

        if( !strcmp( argn[i], "target" )
         || !strcmp( argn[i], "mrl")
         || !strcmp( argn[i], "filename")
         || !strcmp( argn[i], "src") )
        {
            psz_target = argv[i];
        }
        else if( !strcmp( argn[i], "autoplay")
              || !strcmp( argn[i], "autostart") )
        {
            b_autoplay = boolValue(argv[i]);
        }
        else if( !strcmp( argn[i], "fullscreen" ) )
        {
            if( boolValue(argv[i]) )
            {
                ppsz_argv[ppsz_argc++] = "--fullscreen";
            }
            else
            {
                ppsz_argv[ppsz_argc++] = "--no-fullscreen";
            }
        }
        else if( !strcmp( argn[i], "mute" ) )
        {
            if( boolValue(argv[i]) )
            {
                ppsz_argv[ppsz_argc++] = "--volume";
                ppsz_argv[ppsz_argc++] = "0";
            }
        }
        else if( !strcmp( argn[i], "loop")
              || !strcmp( argn[i], "autoloop") )
        {
            if( boolValue(argv[i]) )
            {
                ppsz_argv[ppsz_argc++] = "--loop";
            }
            else {
                ppsz_argv[ppsz_argc++] = "--no-loop";
            }
        }
        else if( !strcmp( argn[i], "version") )
        {
            version = argv[i];
        }
    }

    libvlc_instance = libvlc_new(ppsz_argc, ppsz_argv, NULL);
    if( ! libvlc_instance )
    {
        return NPERR_GENERIC_ERROR;
    }

    /*
    ** fetch plugin base URL, which is the URL of the page containing the plugin
    ** this URL is used for making absolute URL from relative URL that may be
    ** passed as an MRL argument
    */
    NPObject *plugin;

    if( NPERR_NO_ERROR == NPN_GetValue(p_browser, NPNVWindowNPObject, &plugin) )
    {
        /*
        ** is there a better way to get that info ?
        */
        static const char docLocHref[] = "document.location.href";
        NPString script;
        NPVariant result;

        script.utf8characters = docLocHref;
        script.utf8length = sizeof(docLocHref)-1;

        if( NPN_Evaluate(p_browser, plugin, &script, &result) )
        {
            if( NPVARIANT_IS_STRING(result) )
            {
                NPString &location = NPVARIANT_TO_STRING(result);

                psz_baseURL = new char[location.utf8length+1];
                if( psz_baseURL )
                {
                    strncpy(psz_baseURL, location.utf8characters, location.utf8length);
                    psz_baseURL[location.utf8length] = '\0';
                }
            }
            NPN_ReleaseVariantValue(&result);
        }
        NPN_ReleaseObject(plugin);
    }

    if( psz_target )
    {
        // get absolute URL from src
        psz_target = getAbsoluteURL(psz_target);
    }

    /* assign plugin script root class */
    if( (NULL != version) && (!strcmp(version, "VideoLAN.VLCPlugin.2")) )
    {
        /* new APIs */
        scriptClass = RuntimeNPClass<LibvlcRootNPObject>::getClass();
    }
    else
    {
        /* legacy APIs */
        scriptClass = RuntimeNPClass<VlcNPObject>::getClass();
    }

    return NPERR_NO_ERROR;
}

#if 0
#ifdef XP_WIN
/* This is really ugly but there is a deadlock when stopping a stream
 * (in VLC_CleanUp()) because the video output is a child of the drawable but
 * is in a different thread. */
static void HackStopVout( VlcPlugin* p_plugin )
{
    MSG msg;
    HWND hwnd;
    vlc_value_t value;

    int i_vlc = libvlc_get_vlc_id(p_plugin->libvlc_instance);
    VLC_VariableGet( i_vlc, "drawable", &value );

    hwnd = FindWindowEx( (HWND)value.i_int, 0, 0, 0 );
    if( !hwnd ) return;

    PostMessage( hwnd, WM_CLOSE, 0, 0 );

    do
    {
        while( PeekMessage( &msg, (HWND)value.i_int, 0, 0, PM_REMOVE ) )
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        if( FindWindowEx( (HWND)value.i_int, 0, 0, 0 ) ) Sleep( 10 );
    }
    while( (hwnd = FindWindowEx( (HWND)value.i_int, 0, 0, 0 )) );
}
#endif /* XP_WIN */
#endif

VlcPlugin::~VlcPlugin()
{
    delete psz_baseURL;
    delete psz_target;
    if( libvlc_instance )
        libvlc_destroy(libvlc_instance);
}

/*****************************************************************************
 * VlcPlugin methods
 *****************************************************************************/

char *VlcPlugin::getAbsoluteURL(const char *url)
{
    if( NULL != url )
    {
        // check whether URL is already absolute
        const char *end=strchr(url, ':');
        if( (NULL != end) && (end != url) )
        {
            // validate protocol header
            const char *start = url;
            while( start != end ) {
                char c = *start | 0x20;
                if( (c < 'a') || (c > 'z') )
                    // not valid protocol header, assume relative URL
                    break;
                ++start;
            }
            /* we have a protocol header, therefore URL is absolute */
            return strdup(url);
        }

        if( psz_baseURL )
        {
            size_t baseLen = strlen(psz_baseURL);
            char *href = new char[baseLen+strlen(url)];
            if( href )
            {
                /* prepend base URL */
                strcpy(href, psz_baseURL);

                /*
                ** relative url could be empty,
                ** in which case return base URL
                */
                if( '\0' == *url )
                    return href;

                /*
                ** locate pathname part of base URL
                */

                /* skip over protocol part  */
                char *pathstart = strchr(href, ':');
                char *pathend;
                if( '/' == *(++pathstart) )
                {
                    if( '/' == *(++pathstart) )
                    {
                        ++pathstart;
                    }
                }
                /* skip over host part */
                pathstart = strchr(pathstart, '/');
                pathend = href+baseLen;
                if( ! pathstart )
                {
                    // no path, add a / past end of url (over '\0')
                    pathstart = pathend;
                    *pathstart = '/';
                }

                /* relative URL made of an absolute path ? */
                if( '/' == *url )
                {
                    /* replace path completely */
                    strcpy(pathstart, url);
                    return href;
                }

                /* find last path component and replace it */
                while( '/' != *pathend) --pathend;

                /*
                ** if relative url path starts with one or more '../',
                ** factor them out of href so that we return a
                ** normalized URL
                */
                while( pathend != pathstart )
                {
                    const char *p = url;
                    if( '.' != *p )
                        break;
                    ++p;
                    if( '.' != *p )
                        break;
                    ++p;
                    if( '/' != *p )
                        break;
                    ++p;
                    url = p;
                    while( '/' != *pathend ) --pathend;
                }
                /* concatenate remaining base URL and relative URL */
                strcpy(pathend+1, url);
            }
            return href;
        }
    }
    return NULL;
}

#if XP_UNIX
int  VlcPlugin::setSize(unsigned width, unsigned height)
{
    int diff = (width != i_width) || (height != i_height);

    i_width = width;
    i_height = height;

    /* return size */
    return diff;
}
#endif

<commit_msg>Use a separate message bank for each libvlc instance Fix compilation for libvlc users<commit_after>/*****************************************************************************
 * vlcplugin.cpp: a VLC plugin for Mozilla
 *****************************************************************************
 * Copyright (C) 2002-2005 the VideoLAN team
 * $Id$
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
 *          Damien Fouilleul <damienf.fouilleul@laposte.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include "config.h"

#ifdef HAVE_MOZILLA_CONFIG_H
#   include <mozilla-config.h>
#endif

#include "vlcplugin.h"
#include "control/npovlc.h"
#include "control/npolibvlc.h"

/*****************************************************************************
 * VlcPlugin constructor and destructor
 *****************************************************************************/
VlcPlugin::VlcPlugin( NPP instance, uint16 mode ) :
    i_npmode(mode),
    b_stream(0),
    b_autoplay(0),
    psz_target(NULL),
    libvlc_instance(NULL),
    scriptClass(NULL),
    p_browser(instance),
    psz_baseURL(NULL)
#if XP_WIN
    ,pf_wndproc(NULL)
#endif
#if XP_UNIX
    ,i_width((unsigned)-1)
    ,i_height((unsigned)-1)
#endif
{
    memset(&npwindow, 0, sizeof(NPWindow));
}

static int boolValue(const char *value) {
    return ( !strcmp(value, "1") ||
             !strcasecmp(value, "true") ||
             !strcasecmp(value, "yes") );
}

NPError VlcPlugin::init(int argc, char* const argn[], char* const argv[])
{
    /* prepare VLC command line */
    char *ppsz_argv[32] =
    {
        "vlc",
        "-vv",
        "--no-stats",
        "--no-media-library",
        "--intf", "dummy",
    };
    int ppsz_argc = 6;

    /* locate VLC module path */
#ifdef XP_MACOSX
    ppsz_argv[ppsz_argc++] = "--plugin-path";
    ppsz_argv[ppsz_argc++] = "/Library/Internet Plug-Ins/VLC Plugin.plugin/"
                             "Contents/MacOS/modules";
#elif defined(XP_WIN)
    HKEY h_key;
    DWORD i_type, i_data = MAX_PATH + 1;
    char p_data[MAX_PATH + 1];
    if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC",
                      0, KEY_READ, &h_key ) == ERROR_SUCCESS )
    {
         if( RegQueryValueEx( h_key, "InstallDir", 0, &i_type,
                              (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS )
         {
             if( i_type == REG_SZ )
             {
                 strcat( p_data, "\\vlc" );
                 ppsz_argv[0] = p_data;
             }
         }
         RegCloseKey( h_key );
    }
    ppsz_argv[ppsz_argc++] = "--no-one-instance";
#if 0
    ppsz_argv[ppsz_argc++] = "--fast-mutex";
    ppsz_argv[ppsz_argc++] = "--win9x-cv-method=1";
#endif

#endif /* XP_MACOSX */

    const char *version = NULL;

    /* parse plugin arguments */
    for( int i = 0; i < argc ; i++ )
    {
        fprintf(stderr, "argn=%s, argv=%s\n", argn[i], argv[i]);

        if( !strcmp( argn[i], "target" )
         || !strcmp( argn[i], "mrl")
         || !strcmp( argn[i], "filename")
         || !strcmp( argn[i], "src") )
        {
            psz_target = argv[i];
        }
        else if( !strcmp( argn[i], "autoplay")
              || !strcmp( argn[i], "autostart") )
        {
            b_autoplay = boolValue(argv[i]);
        }
        else if( !strcmp( argn[i], "fullscreen" ) )
        {
            if( boolValue(argv[i]) )
            {
                ppsz_argv[ppsz_argc++] = "--fullscreen";
            }
            else
            {
                ppsz_argv[ppsz_argc++] = "--no-fullscreen";
            }
        }
        else if( !strcmp( argn[i], "mute" ) )
        {
            if( boolValue(argv[i]) )
            {
                ppsz_argv[ppsz_argc++] = "--volume";
                ppsz_argv[ppsz_argc++] = "0";
            }
        }
        else if( !strcmp( argn[i], "loop")
              || !strcmp( argn[i], "autoloop") )
        {
            if( boolValue(argv[i]) )
            {
                ppsz_argv[ppsz_argc++] = "--loop";
            }
            else {
                ppsz_argv[ppsz_argc++] = "--no-loop";
            }
        }
        else if( !strcmp( argn[i], "version") )
        {
            version = argv[i];
        }
    }

    libvlc_instance = libvlc_new(ppsz_argc, ppsz_argv, NULL);
    if( ! libvlc_instance )
    {
        return NPERR_GENERIC_ERROR;
    }

    /*
    ** fetch plugin base URL, which is the URL of the page containing the plugin
    ** this URL is used for making absolute URL from relative URL that may be
    ** passed as an MRL argument
    */
    NPObject *plugin;

    if( NPERR_NO_ERROR == NPN_GetValue(p_browser, NPNVWindowNPObject, &plugin) )
    {
        /*
        ** is there a better way to get that info ?
        */
        static const char docLocHref[] = "document.location.href";
        NPString script;
        NPVariant result;

        script.utf8characters = docLocHref;
        script.utf8length = sizeof(docLocHref)-1;

        if( NPN_Evaluate(p_browser, plugin, &script, &result) )
        {
            if( NPVARIANT_IS_STRING(result) )
            {
                NPString &location = NPVARIANT_TO_STRING(result);

                psz_baseURL = new char[location.utf8length+1];
                if( psz_baseURL )
                {
                    strncpy(psz_baseURL, location.utf8characters, location.utf8length);
                    psz_baseURL[location.utf8length] = '\0';
                }
            }
            NPN_ReleaseVariantValue(&result);
        }
        NPN_ReleaseObject(plugin);
    }

    if( psz_target )
    {
        // get absolute URL from src
        psz_target = getAbsoluteURL(psz_target);
    }

    /* assign plugin script root class */
    if( (NULL != version) && (!strcmp(version, "VideoLAN.VLCPlugin.2")) )
    {
        /* new APIs */
        scriptClass = RuntimeNPClass<LibvlcRootNPObject>::getClass();
    }
    else
    {
        /* legacy APIs */
        scriptClass = RuntimeNPClass<VlcNPObject>::getClass();
    }

    return NPERR_NO_ERROR;
}

#if 0
#ifdef XP_WIN
/* This is really ugly but there is a deadlock when stopping a stream
 * (in VLC_CleanUp()) because the video output is a child of the drawable but
 * is in a different thread. */
static void HackStopVout( VlcPlugin* p_plugin )
{
    MSG msg;
    HWND hwnd;
    vlc_value_t value;

    int i_vlc = libvlc_get_vlc_id(p_plugin->libvlc_instance);
    VLC_VariableGet( i_vlc, "drawable", &value );

    hwnd = FindWindowEx( (HWND)value.i_int, 0, 0, 0 );
    if( !hwnd ) return;

    PostMessage( hwnd, WM_CLOSE, 0, 0 );

    do
    {
        while( PeekMessage( &msg, (HWND)value.i_int, 0, 0, PM_REMOVE ) )
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        if( FindWindowEx( (HWND)value.i_int, 0, 0, 0 ) ) Sleep( 10 );
    }
    while( (hwnd = FindWindowEx( (HWND)value.i_int, 0, 0, 0 )) );
}
#endif /* XP_WIN */
#endif

VlcPlugin::~VlcPlugin()
{
    delete psz_baseURL;
    delete psz_target;
    if( libvlc_instance )
        libvlc_destroy(libvlc_instance, NULL );
}

/*****************************************************************************
 * VlcPlugin methods
 *****************************************************************************/

char *VlcPlugin::getAbsoluteURL(const char *url)
{
    if( NULL != url )
    {
        // check whether URL is already absolute
        const char *end=strchr(url, ':');
        if( (NULL != end) && (end != url) )
        {
            // validate protocol header
            const char *start = url;
            while( start != end ) {
                char c = *start | 0x20;
                if( (c < 'a') || (c > 'z') )
                    // not valid protocol header, assume relative URL
                    break;
                ++start;
            }
            /* we have a protocol header, therefore URL is absolute */
            return strdup(url);
        }

        if( psz_baseURL )
        {
            size_t baseLen = strlen(psz_baseURL);
            char *href = new char[baseLen+strlen(url)];
            if( href )
            {
                /* prepend base URL */
                strcpy(href, psz_baseURL);

                /*
                ** relative url could be empty,
                ** in which case return base URL
                */
                if( '\0' == *url )
                    return href;

                /*
                ** locate pathname part of base URL
                */

                /* skip over protocol part  */
                char *pathstart = strchr(href, ':');
                char *pathend;
                if( '/' == *(++pathstart) )
                {
                    if( '/' == *(++pathstart) )
                    {
                        ++pathstart;
                    }
                }
                /* skip over host part */
                pathstart = strchr(pathstart, '/');
                pathend = href+baseLen;
                if( ! pathstart )
                {
                    // no path, add a / past end of url (over '\0')
                    pathstart = pathend;
                    *pathstart = '/';
                }

                /* relative URL made of an absolute path ? */
                if( '/' == *url )
                {
                    /* replace path completely */
                    strcpy(pathstart, url);
                    return href;
                }

                /* find last path component and replace it */
                while( '/' != *pathend) --pathend;

                /*
                ** if relative url path starts with one or more '../',
                ** factor them out of href so that we return a
                ** normalized URL
                */
                while( pathend != pathstart )
                {
                    const char *p = url;
                    if( '.' != *p )
                        break;
                    ++p;
                    if( '.' != *p )
                        break;
                    ++p;
                    if( '/' != *p )
                        break;
                    ++p;
                    url = p;
                    while( '/' != *pathend ) --pathend;
                }
                /* concatenate remaining base URL and relative URL */
                strcpy(pathend+1, url);
            }
            return href;
        }
    }
    return NULL;
}

#if XP_UNIX
int  VlcPlugin::setSize(unsigned width, unsigned height)
{
    int diff = (width != i_width) || (height != i_height);

    i_width = width;
    i_height = height;

    /* return size */
    return diff;
}
#endif

<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/autocomplete/shortcuts_provider.h"

#include <algorithm>
#include <cmath>
#include <map>
#include <vector>

#include "base/i18n/break_iterator.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "googleurl/src/url_parse.h"
#include "googleurl/src/url_util.h"
#include "net/base/escape.h"
#include "net/base/net_util.h"

namespace {

class RemoveMatchPredicate {
 public:
  explicit RemoveMatchPredicate(const std::set<GURL>& urls)
      : urls_(urls) {
  }
  bool operator()(const AutocompleteMatch& match) {
    return urls_.find(match.destination_url) != urls_.end();
  }
 private:
  // Lifetime of the object is less than the lifetime of passed |urls|, so
  // it is safe to store reference.
  const std::set<GURL>& urls_;
};

}  // namespace

ShortcutsProvider::ShortcutsProvider(ACProviderListener* listener,
                                     Profile* profile)
    : AutocompleteProvider(listener, profile, "ShortcutsProvider"),
      languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
      initialized_(false),
      shortcuts_backend_(profile->GetShortcutsBackend()) {
  if (shortcuts_backend_.get()) {
    shortcuts_backend_->AddObserver(this);
    if (shortcuts_backend_->initialized())
      initialized_ = true;
  }
}

void ShortcutsProvider::Start(const AutocompleteInput& input,
                              bool minimal_changes) {
  matches_.clear();

  if ((input.type() == AutocompleteInput::INVALID) ||
      (input.type() == AutocompleteInput::FORCED_QUERY))
    return;

  if (input.text().empty())
    return;

  if (!initialized_)
    return;

  base::TimeTicks start_time = base::TimeTicks::Now();
  GetMatches(input);
  if (input.text().length() < 6) {
    base::TimeTicks end_time = base::TimeTicks::Now();
    std::string name = "ShortcutsProvider.QueryIndexTime." +
        base::IntToString(input.text().size());
    base::Histogram* counter = base::Histogram::FactoryGet(
        name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag);
    counter->Add(static_cast<int>((end_time - start_time).InMilliseconds()));
  }
  UpdateStarredStateOfMatches();
}

void ShortcutsProvider::DeleteMatch(const AutocompleteMatch& match) {
  // When a user deletes a match, he probably means for the URL to disappear out
  // of history entirely. So nuke all shortcuts that map to this URL.
  std::set<GURL> url;
  url.insert(match.destination_url);
  // Immediately delete matches and shortcuts with the URL, so we can update the
  // controller synchronously.
  DeleteShortcutsWithURLs(url);
  DeleteMatchesWithURLs(url);

  // Delete the match from the history DB. This will eventually result in a
  // second call to DeleteShortcutsWithURLs(), which is harmless.
  HistoryService* const history_service =
      HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);

  DCHECK(history_service && match.destination_url.is_valid());
  history_service->DeleteURL(match.destination_url);
}

ShortcutsProvider::~ShortcutsProvider() {
  if (shortcuts_backend_.get())
    shortcuts_backend_->RemoveObserver(this);
}

void ShortcutsProvider::OnShortcutsLoaded() {
  initialized_ = true;
}

void ShortcutsProvider::DeleteMatchesWithURLs(const std::set<GURL>& urls) {
  std::remove_if(matches_.begin(), matches_.end(), RemoveMatchPredicate(urls));
  listener_->OnProviderUpdate(true);
}

void ShortcutsProvider::DeleteShortcutsWithURLs(const std::set<GURL>& urls) {
  if (!shortcuts_backend_.get())
    return;  // We are off the record.
  for (std::set<GURL>::const_iterator url = urls.begin(); url != urls.end();
       ++url)
    shortcuts_backend_->DeleteShortcutsWithUrl(*url);
}

void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
  // Get the URLs from the shortcuts database with keys that partially or
  // completely match the search term.
  string16 term_string(base::i18n::ToLower(input.text()));
  DCHECK(!term_string.empty());

  for (history::ShortcutsBackend::ShortcutMap::const_iterator it =
       FindFirstMatch(term_string);
       it != shortcuts_backend_->shortcuts_map().end() &&
            StartsWith(it->first, term_string, true); ++it)
    matches_.push_back(ShortcutToACMatch(input, term_string, it->second));
  std::partial_sort(matches_.begin(),
      matches_.begin() +
          std::min(AutocompleteProvider::kMaxMatches, matches_.size()),
      matches_.end(), &AutocompleteMatch::MoreRelevant);
  if (matches_.size() > AutocompleteProvider::kMaxMatches) {
    matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches,
                   matches_.end());
  }
}

AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
    const AutocompleteInput& input,
    const string16& term_string,
    const history::ShortcutsBackend::Shortcut& shortcut) {
  AutocompleteMatch match(this, CalculateScore(term_string, shortcut),
                          true, AutocompleteMatch::HISTORY_TITLE);
  match.destination_url = shortcut.url;
  DCHECK(match.destination_url.is_valid());
  match.fill_into_edit = UTF8ToUTF16(shortcut.url.spec());

  match.contents = shortcut.contents;
  match.contents_class = ClassifyAllMatchesInString(term_string,
                                                    match.contents,
                                                    shortcut.contents_class);

  match.description = shortcut.description;
  match.description_class = ClassifyAllMatchesInString(
      term_string, match.description, shortcut.description_class);

  return match;
}

// static
ACMatchClassifications ShortcutsProvider::ClassifyAllMatchesInString(
    const string16& find_text,
    const string16& text,
    const ACMatchClassifications& original_class) {
  DCHECK(!find_text.empty());

  base::i18n::BreakIterator term_iter(find_text,
                                      base::i18n::BreakIterator::BREAK_WORD);
  if (!term_iter.Init())
    return original_class;

  std::vector<string16> terms;
  while (term_iter.Advance()) {
    if (term_iter.IsWord())
      terms.push_back(term_iter.GetString());
  }
  // Sort the strings so that longer strings appear after their prefixes, if
  // any.
  std::sort(terms.begin(), terms.end());

  // Find the earliest match of any word in |find_text| in the |text|. Add to
  // |match_class|. Move pointer after match. Repeat until all matches are
  // found.
  string16 text_lowercase(base::i18n::ToLower(text));
  ACMatchClassifications match_class;
  // |match_class| should start at the position 0, if the matched text start
  // from the position 0, this will be popped from the vector further down.
  match_class.push_back(ACMatchClassification(0, ACMatchClassification::NONE));
  for (size_t last_position = 0; last_position < text_lowercase.length();) {
    size_t match_start = text_lowercase.length();
    size_t match_end = last_position;

    for (size_t i = 0; i < terms.size(); ++i) {
      size_t match = text_lowercase.find(terms[i], last_position);
      // Use <= in conjunction with the sort() call above so that longer strings
      // are matched in preference to their prefixes.
      if (match != string16::npos && match <= match_start) {
        match_start = match;
        match_end = match + terms[i].length();
      }
    }

    if (match_start >= match_end)
      break;

    // Collapse adjacent ranges into one.
    if (!match_class.empty() && match_class.back().offset == match_start)
      match_class.pop_back();

    AutocompleteMatch::AddLastClassificationIfNecessary(&match_class,
        match_start, ACMatchClassification::MATCH);
    if (match_end < text_lowercase.length()) {
      AutocompleteMatch::AddLastClassificationIfNecessary(&match_class,
          match_end, ACMatchClassification::NONE);
    }

    last_position = match_end;
  }

  // Merge match-marking data with original classifications.
  if (match_class.empty())
    return original_class;

  ACMatchClassifications output;
  for (ACMatchClassifications::const_iterator i = original_class.begin(),
       j = match_class.begin(); i != original_class.end();) {
    AutocompleteMatch::AddLastClassificationIfNecessary(&output,
        std::max(i->offset, j->offset), i->style | j->style);
    const size_t next_i_offset = (i + 1) == original_class.end() ?
        static_cast<size_t>(-1) : (i + 1)->offset;
    const size_t next_j_offset = (j + 1) == match_class.end() ?
        static_cast<size_t>(-1) : (j + 1)->offset;
    if (next_i_offset >= next_j_offset)
      ++j;
    if (next_j_offset >= next_i_offset)
      ++i;
  }

  return output;
}

history::ShortcutsBackend::ShortcutMap::const_iterator
    ShortcutsProvider::FindFirstMatch(const string16& keyword) {
  history::ShortcutsBackend::ShortcutMap::const_iterator it =
      shortcuts_backend_->shortcuts_map().lower_bound(keyword);
  // Lower bound not necessarily matches the keyword, check for item pointed by
  // the lower bound iterator to at least start with keyword.
  return ((it == shortcuts_backend_->shortcuts_map().end()) ||
    StartsWith(it->first, keyword, true)) ? it :
    shortcuts_backend_->shortcuts_map().end();
}

// static
int ShortcutsProvider::CalculateScore(
    const string16& terms,
    const history::ShortcutsBackend::Shortcut& shortcut) {
  DCHECK(!terms.empty());
  DCHECK_LE(terms.length(), shortcut.text.length());

  // The initial score is based on how much of the shortcut the user has typed.
  // Using the square root of the typed fraction boosts the base score rapidly
  // as characters are typed, compared with simply using the typed fraction
  // directly. This makes sense since the first characters typed are much more
  // important for determining how likely it is a user wants a particular
  // shortcut than are the remaining continued characters.
  double base_score = (AutocompleteResult::kLowestDefaultScore - 1) *
      sqrt(static_cast<double>(terms.length()) / shortcut.text.length());

  // Then we decay this by half each week.
  const double kLn2 = 0.6931471805599453;
  base::TimeDelta time_passed = base::Time::Now() - shortcut.last_access_time;
  // Clamp to 0 in case time jumps backwards (e.g. due to DST).
  double decay_exponent = std::max(0.0, kLn2 * static_cast<double>(
      time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek);

  // We modulate the decay factor based on how many times the shortcut has been
  // used. Newly created shortcuts decay at full speed; otherwise, decaying by
  // half takes |n| times as much time, where n increases by
  // (1.0 / each 5 additional hits), up to a maximum of 5x as long.
  const double kMaxDecaySpeedDivisor = 5.0;
  const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0;
  double decay_divisor = std::min(kMaxDecaySpeedDivisor,
      (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
      kNumUsesPerDecaySpeedDivisorIncrement);

  return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) +
      0.5);
}

void ShortcutsProvider::set_shortcuts_backend(
    history::ShortcutsBackend* shortcuts_backend) {
  DCHECK(shortcuts_backend);
  shortcuts_backend_ = shortcuts_backend;
  shortcuts_backend_->AddObserver(this);
  if (shortcuts_backend_->initialized())
    initialized_ = true;
}
<commit_msg>Fix use-after-free in ShortcutsProvider::DeleteMatch().<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/autocomplete/shortcuts_provider.h"

#include <algorithm>
#include <cmath>
#include <map>
#include <vector>

#include "base/i18n/break_iterator.h"
#include "base/i18n/case_conversion.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/net/url_fixer_upper.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "googleurl/src/url_parse.h"
#include "googleurl/src/url_util.h"
#include "net/base/escape.h"
#include "net/base/net_util.h"

namespace {

class RemoveMatchPredicate {
 public:
  explicit RemoveMatchPredicate(const std::set<GURL>& urls)
      : urls_(urls) {
  }
  bool operator()(const AutocompleteMatch& match) {
    return urls_.find(match.destination_url) != urls_.end();
  }
 private:
  // Lifetime of the object is less than the lifetime of passed |urls|, so
  // it is safe to store reference.
  const std::set<GURL>& urls_;
};

}  // namespace

ShortcutsProvider::ShortcutsProvider(ACProviderListener* listener,
                                     Profile* profile)
    : AutocompleteProvider(listener, profile, "ShortcutsProvider"),
      languages_(profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)),
      initialized_(false),
      shortcuts_backend_(profile->GetShortcutsBackend()) {
  if (shortcuts_backend_.get()) {
    shortcuts_backend_->AddObserver(this);
    if (shortcuts_backend_->initialized())
      initialized_ = true;
  }
}

void ShortcutsProvider::Start(const AutocompleteInput& input,
                              bool minimal_changes) {
  matches_.clear();

  if ((input.type() == AutocompleteInput::INVALID) ||
      (input.type() == AutocompleteInput::FORCED_QUERY))
    return;

  if (input.text().empty())
    return;

  if (!initialized_)
    return;

  base::TimeTicks start_time = base::TimeTicks::Now();
  GetMatches(input);
  if (input.text().length() < 6) {
    base::TimeTicks end_time = base::TimeTicks::Now();
    std::string name = "ShortcutsProvider.QueryIndexTime." +
        base::IntToString(input.text().size());
    base::Histogram* counter = base::Histogram::FactoryGet(
        name, 1, 1000, 50, base::Histogram::kUmaTargetedHistogramFlag);
    counter->Add(static_cast<int>((end_time - start_time).InMilliseconds()));
  }
  UpdateStarredStateOfMatches();
}

void ShortcutsProvider::DeleteMatch(const AutocompleteMatch& match) {
  // Copy the URL since DeleteMatchesWithURLs() will invalidate |match|.
  GURL url(match.destination_url);

  // When a user deletes a match, he probably means for the URL to disappear out
  // of history entirely. So nuke all shortcuts that map to this URL.
  std::set<GURL> urls;
  urls.insert(url);
  // Immediately delete matches and shortcuts with the URL, so we can update the
  // controller synchronously.
  DeleteShortcutsWithURLs(urls);
  DeleteMatchesWithURLs(urls);  // NOTE: |match| is now dead!

  // Delete the match from the history DB. This will eventually result in a
  // second call to DeleteShortcutsWithURLs(), which is harmless.
  HistoryService* const history_service =
      HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);

  DCHECK(history_service && url.is_valid());
  history_service->DeleteURL(url);
}

ShortcutsProvider::~ShortcutsProvider() {
  if (shortcuts_backend_.get())
    shortcuts_backend_->RemoveObserver(this);
}

void ShortcutsProvider::OnShortcutsLoaded() {
  initialized_ = true;
}

void ShortcutsProvider::DeleteMatchesWithURLs(const std::set<GURL>& urls) {
  std::remove_if(matches_.begin(), matches_.end(), RemoveMatchPredicate(urls));
  listener_->OnProviderUpdate(true);
}

void ShortcutsProvider::DeleteShortcutsWithURLs(const std::set<GURL>& urls) {
  if (!shortcuts_backend_.get())
    return;  // We are off the record.
  for (std::set<GURL>::const_iterator url = urls.begin(); url != urls.end();
       ++url)
    shortcuts_backend_->DeleteShortcutsWithUrl(*url);
}

void ShortcutsProvider::GetMatches(const AutocompleteInput& input) {
  // Get the URLs from the shortcuts database with keys that partially or
  // completely match the search term.
  string16 term_string(base::i18n::ToLower(input.text()));
  DCHECK(!term_string.empty());

  for (history::ShortcutsBackend::ShortcutMap::const_iterator it =
       FindFirstMatch(term_string);
       it != shortcuts_backend_->shortcuts_map().end() &&
            StartsWith(it->first, term_string, true); ++it)
    matches_.push_back(ShortcutToACMatch(input, term_string, it->second));
  std::partial_sort(matches_.begin(),
      matches_.begin() +
          std::min(AutocompleteProvider::kMaxMatches, matches_.size()),
      matches_.end(), &AutocompleteMatch::MoreRelevant);
  if (matches_.size() > AutocompleteProvider::kMaxMatches) {
    matches_.erase(matches_.begin() + AutocompleteProvider::kMaxMatches,
                   matches_.end());
  }
}

AutocompleteMatch ShortcutsProvider::ShortcutToACMatch(
    const AutocompleteInput& input,
    const string16& term_string,
    const history::ShortcutsBackend::Shortcut& shortcut) {
  AutocompleteMatch match(this, CalculateScore(term_string, shortcut),
                          true, AutocompleteMatch::HISTORY_TITLE);
  match.destination_url = shortcut.url;
  DCHECK(match.destination_url.is_valid());
  match.fill_into_edit = UTF8ToUTF16(shortcut.url.spec());

  match.contents = shortcut.contents;
  match.contents_class = ClassifyAllMatchesInString(term_string,
                                                    match.contents,
                                                    shortcut.contents_class);

  match.description = shortcut.description;
  match.description_class = ClassifyAllMatchesInString(
      term_string, match.description, shortcut.description_class);

  return match;
}

// static
ACMatchClassifications ShortcutsProvider::ClassifyAllMatchesInString(
    const string16& find_text,
    const string16& text,
    const ACMatchClassifications& original_class) {
  DCHECK(!find_text.empty());

  base::i18n::BreakIterator term_iter(find_text,
                                      base::i18n::BreakIterator::BREAK_WORD);
  if (!term_iter.Init())
    return original_class;

  std::vector<string16> terms;
  while (term_iter.Advance()) {
    if (term_iter.IsWord())
      terms.push_back(term_iter.GetString());
  }
  // Sort the strings so that longer strings appear after their prefixes, if
  // any.
  std::sort(terms.begin(), terms.end());

  // Find the earliest match of any word in |find_text| in the |text|. Add to
  // |match_class|. Move pointer after match. Repeat until all matches are
  // found.
  string16 text_lowercase(base::i18n::ToLower(text));
  ACMatchClassifications match_class;
  // |match_class| should start at the position 0, if the matched text start
  // from the position 0, this will be popped from the vector further down.
  match_class.push_back(ACMatchClassification(0, ACMatchClassification::NONE));
  for (size_t last_position = 0; last_position < text_lowercase.length();) {
    size_t match_start = text_lowercase.length();
    size_t match_end = last_position;

    for (size_t i = 0; i < terms.size(); ++i) {
      size_t match = text_lowercase.find(terms[i], last_position);
      // Use <= in conjunction with the sort() call above so that longer strings
      // are matched in preference to their prefixes.
      if (match != string16::npos && match <= match_start) {
        match_start = match;
        match_end = match + terms[i].length();
      }
    }

    if (match_start >= match_end)
      break;

    // Collapse adjacent ranges into one.
    if (!match_class.empty() && match_class.back().offset == match_start)
      match_class.pop_back();

    AutocompleteMatch::AddLastClassificationIfNecessary(&match_class,
        match_start, ACMatchClassification::MATCH);
    if (match_end < text_lowercase.length()) {
      AutocompleteMatch::AddLastClassificationIfNecessary(&match_class,
          match_end, ACMatchClassification::NONE);
    }

    last_position = match_end;
  }

  // Merge match-marking data with original classifications.
  if (match_class.empty())
    return original_class;

  ACMatchClassifications output;
  for (ACMatchClassifications::const_iterator i = original_class.begin(),
       j = match_class.begin(); i != original_class.end();) {
    AutocompleteMatch::AddLastClassificationIfNecessary(&output,
        std::max(i->offset, j->offset), i->style | j->style);
    const size_t next_i_offset = (i + 1) == original_class.end() ?
        static_cast<size_t>(-1) : (i + 1)->offset;
    const size_t next_j_offset = (j + 1) == match_class.end() ?
        static_cast<size_t>(-1) : (j + 1)->offset;
    if (next_i_offset >= next_j_offset)
      ++j;
    if (next_j_offset >= next_i_offset)
      ++i;
  }

  return output;
}

history::ShortcutsBackend::ShortcutMap::const_iterator
    ShortcutsProvider::FindFirstMatch(const string16& keyword) {
  history::ShortcutsBackend::ShortcutMap::const_iterator it =
      shortcuts_backend_->shortcuts_map().lower_bound(keyword);
  // Lower bound not necessarily matches the keyword, check for item pointed by
  // the lower bound iterator to at least start with keyword.
  return ((it == shortcuts_backend_->shortcuts_map().end()) ||
    StartsWith(it->first, keyword, true)) ? it :
    shortcuts_backend_->shortcuts_map().end();
}

// static
int ShortcutsProvider::CalculateScore(
    const string16& terms,
    const history::ShortcutsBackend::Shortcut& shortcut) {
  DCHECK(!terms.empty());
  DCHECK_LE(terms.length(), shortcut.text.length());

  // The initial score is based on how much of the shortcut the user has typed.
  // Using the square root of the typed fraction boosts the base score rapidly
  // as characters are typed, compared with simply using the typed fraction
  // directly. This makes sense since the first characters typed are much more
  // important for determining how likely it is a user wants a particular
  // shortcut than are the remaining continued characters.
  double base_score = (AutocompleteResult::kLowestDefaultScore - 1) *
      sqrt(static_cast<double>(terms.length()) / shortcut.text.length());

  // Then we decay this by half each week.
  const double kLn2 = 0.6931471805599453;
  base::TimeDelta time_passed = base::Time::Now() - shortcut.last_access_time;
  // Clamp to 0 in case time jumps backwards (e.g. due to DST).
  double decay_exponent = std::max(0.0, kLn2 * static_cast<double>(
      time_passed.InMicroseconds()) / base::Time::kMicrosecondsPerWeek);

  // We modulate the decay factor based on how many times the shortcut has been
  // used. Newly created shortcuts decay at full speed; otherwise, decaying by
  // half takes |n| times as much time, where n increases by
  // (1.0 / each 5 additional hits), up to a maximum of 5x as long.
  const double kMaxDecaySpeedDivisor = 5.0;
  const double kNumUsesPerDecaySpeedDivisorIncrement = 5.0;
  double decay_divisor = std::min(kMaxDecaySpeedDivisor,
      (shortcut.number_of_hits + kNumUsesPerDecaySpeedDivisorIncrement - 1) /
      kNumUsesPerDecaySpeedDivisorIncrement);

  return static_cast<int>((base_score / exp(decay_exponent / decay_divisor)) +
      0.5);
}

void ShortcutsProvider::set_shortcuts_backend(
    history::ShortcutsBackend* shortcuts_backend) {
  DCHECK(shortcuts_backend);
  shortcuts_backend_ = shortcuts_backend;
  shortcuts_backend_->AddObserver(this);
  if (shortcuts_backend_->initialized())
    initialized_ = true;
}
<|endoftext|>


<commit_before>#ifndef ABOUTWINDOW_H
#define DACTWINDOW_H

#include <QSharedPointer>
#include <QWidget>

namespace Ui {
  class AboutWindow;
}

class QKeyEvent;

class AboutWindow : public QWidget {
    Q_OBJECT
public:
    AboutWindow(QWidget *parent = 0, Qt::WindowFlags f = 0);
    ~AboutWindow();

protected:
    void keyPressEvent(QKeyEvent *event);

private slots:
    void reportBug();

private:
    QSharedPointer<Ui::AboutWindow> d_ui;
};

#endif // ABOUTWINDOW_H
<commit_msg>Fixed old include guards error<commit_after>#ifndef ABOUTWINDOW_H
#define ABOUTWINDOW_H

#include <QSharedPointer>
#include <QWidget>

namespace Ui {
  class AboutWindow;
}

class QKeyEvent;

class AboutWindow : public QWidget {
    Q_OBJECT
public:
    AboutWindow(QWidget *parent = 0, Qt::WindowFlags f = 0);
    ~AboutWindow();

protected:
    void keyPressEvent(QKeyEvent *event);

private slots:
    void reportBug();

private:
    QSharedPointer<Ui::AboutWindow> d_ui;
};

#endif // ABOUTWINDOW_H
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <fstream>
using namespace std;

template<typename T>
struct Node
{
	T x;
	Node<T> * left;
	Node<T> * right;
	Node(T const& value) : x{ value }, left{ nullptr }, right{ nullptr } {}
};

template<typename T>
class Tree
{
private:
	Node<T> * root;
public:
	Tree()
	{
		root  = nullptr;
	}

	~Tree()
	{
		deleteNode(root);
	}

	void deleteNode(Node<T> * node)
	{
		if (node == nullptr) return;
		deleteNode(node->left);
		deleteNode(node->right);
		delete node;
	}

	T x_() const
	{
		return root->x;
	}

	Node<T> * left_() const
	{
		return root->left;
	}

	Node<T> * right_() const
	{
		return root->right;
	}

	Node<T> * root_() const
	{
		return root;
	}

	void insert(const T& value)
	{
		insert(root, value);
	}

	void insert(Node<T>* & node, const T& value)
	{
		if (node) {
			if (value < node->x) {
				insert(node->left, value);
			}
			else if (value > node->x) {
				insert(node->right, value);
			}
			else {
				return;
			}
		}
		else {
			node = new Node<T>(value);
		}
	}

	Node<T> * search(const T& x)const
	{
		Node<T> * curEl = root;
		while (curEl != nullptr)
		{
			if (curEl->x == x)
				break;
			else
			{
				if (x > curEl->x)
					curEl = curEl->right;
				else curEl = curEl->left;
			}
		}
		return curEl;
	}

	bool check_search(const T& x)
	{
		Node<T> * node;
		node = search(x);
		if (node != nullptr)
			return true;
		else return false;
	}

	void fIn(const string filename)
	{
		ifstream fin;
		unsigned int k;
		fin.open(filename);
		if (!fin.is_open())
			cout << "The file isn't find" << endl;
		else
		{
			deleteNode(root);
			if (fin.eof()) return;
			else
			{
				fin >> k;
				T newEl;
				for (unsigned int i = 0; i < k; ++i)
				{
					fin >> newEl;
					insert(newEl);
				}
			}
			fin.close();
		}
	}

	unsigned int size(Node<T> * node)const
	{
		unsigned int size_ = 0;
		if (node != nullptr)
			size_ = size(node->left) + 1 + size(node->right);
		return size_;
	}

	void out_to_file(const string filename)const
	{
		ofstream fout;
		fout.open(filename);
		if (!fout.is_open())
			cout << "The file isn't find" << endl;
		else
		{
			unsigned int size_ = size(root);
			if (size_ == 0)
				return;
			fout << size_ << "\t";
			fOut(root, fout);
			fout.close();
		}
	}

	void fOut(Node<T> * node, ostream&stream)const
	{
		if (node != nullptr)
		{
			fOut(node->left, stream);
			stream << node->x << " ";
			fOut(node->right, stream);
		}
	}

	void out(ostream & stream)const
	{
		Out(root, stream, 0);
	}

	void Out(Node<T> * node, ostream&stream, size_t level)const
	{
		Node<T> * curEl = node;
		if (curEl != nullptr)
		{
			Out(curEl->right, stream, level + 1);
			for (unsigned int i = 0; i < level; ++i)
				stream << '-';
			stream << curEl->x << endl;
			Out(curEl->left, stream, level + 1);
		}
	}
};
<commit_msg>Update BinaryTree.hpp<commit_after>#include <iostream>
#include <string>
#include <fstream>
using namespace std;

template<typename T>
struct Node
{
	T x;
	Node<T> * left;
	Node<T> * right;
	Node(T const& value) : x{ value }, left{ nullptr }, right{ nullptr } {}
};

template<typename T>
class Tree
{
private:
	Node<T> * root;
public:
	Tree()
	{
		root  = nullptr;
	}

	~Tree()
	{
		deleteNode(root);
	}

	void deleteNode(Node<T> * node)
	{
		if (node == nullptr) return;
		deleteNode(node->left);
		deleteNode(node->right);
		delete node;
	}

	T x_() const
	{
		return root->x;
	}

	Node<T> * left_() const
	{
		return root->left;
	}

	Node<T> * right_() const
	{
		return root->right;
	}

	Node<T> * root_() const
	{
		return root;
	}

	void insert(const T& value)
	{
		insert(root, value);
	}

	void insert(Node<T>* & node, const T& value)
	{
		if (node)
		{
			if (value < node->x)
				insert(node->left, value);
			else if (value > node->x)
				insert(node->right, value);
			else return;
		}
		else node = new Node<T>(value);
	}

	Node<T> * search(const T& x)const
	{
		Node<T> * curEl = root;
		while (curEl != nullptr)
		{
			if (curEl->x == x)
				break;
			else
			{
				if (x > curEl->x)
					curEl = curEl->right;
				else curEl = curEl->left;
			}
		}
		return curEl;
	}

	bool check_search(const T& x)
	{
		Node<T> * node;
		node = search(x);
		if (node != nullptr)
			return true;
		else return false;
	}

	void fIn(const string filename)
	{
		ifstream fin;
		unsigned int k;
		fin.open(filename);
		if (!fin.is_open())
			cout << "The file isn't find" << endl;
		else
		{
			deleteNode(root);
			if (fin.eof()) return;
			else
			{
				fin >> k;
				T newEl;
				for (unsigned int i = 0; i < k; ++i)
				{
					fin >> newEl;
					insert(newEl);
				}
			}
			fin.close();
		}
	}

	unsigned int size(Node<T> * node)const
	{
		unsigned int size_ = 0;
		if (node != nullptr)
			size_ = size(node->left) + 1 + size(node->right);
		return size_;
	}

	void out_to_file(const string filename)const
	{
		ofstream fout;
		fout.open(filename);
		if (!fout.is_open())
			cout << "The file isn't find" << endl;
		else
		{
			unsigned int size_ = size(root);
			if (size_ == 0)
				return;
			fout << size_ << "\t";
			fOut(root, fout);
			fout.close();
		}
	}

	void fOut(Node<T> * node, ostream&stream)const
	{
		if (node != nullptr)
		{
			fOut(node->left, stream);
			stream << node->x << " ";
			fOut(node->right, stream);
		}
	}

	void out(ostream & stream)const
	{
		Out(root, stream, 0);
	}

	void Out(Node<T> * node, ostream&stream, size_t level)const
	{
		Node<T> * curEl = node;
		if (curEl != nullptr)
		{
			Out(curEl->right, stream, level + 1);
			for (unsigned int i = 0; i < level; ++i)
				stream << '-';
			stream << curEl->x << endl;
			Out(curEl->left, stream, level + 1);
		}
	}

	Node<T> * prev_(const T& x)
	{
		return prev(root, x);
	}

	Node<T> * prev_(Node<T> * & node, const T& x)
	{
		if (check_search(x))
		{
			Node<T> * prev = nullptr;
			Node<T> * cur = nullptr;
			while (node->x != x)
			{
				if (x < node->x)
				{
					prev = node;
					cur = node->left;
					prev(cur, x);
				}
				else if (x > node->x)
				{
					prev = node;
					cur = node->right;
					prev(cur, x);
				}
			}
			return prev;
		}
		else return;
	}

	void deliteX(const T& x)
	{
		Node<T> * curEl = search(x);
		Node<T> * prev = nullptr;
		if (curEl != nullptr)
		{
			if (curEl->left == nullptr&&curEl->right == nullptr)
			{
				prev = prev_(x);
				if (x < prev->x)
					prev->left = nullptr;
				if (x > prev->x)
					prev->right = nullptr;
			}
			else
			{
				if (curEl->right != nullptr)
				{
					Node<T> * left_ = curEl->left;
					Node<T> * right_ = curEl->right;
					while (curEl->right->left)
					{

					}
				}
			}
		}
		else return;
	}
};
<|endoftext|>


<commit_before>#include "Pch.h"

#include "User.h"
#include "WorldState.h"
#include "CommandTable.h"
#include "Room.h"

namespace Game {

User::User (ScriptWorld * world, Scriptable * boundScriptable, WorldState * worldState)
	: m_world(world),
	  m_scriptable(boundScriptable),
	  m_worldState(worldState),
	  m_room(nullptr)
{
	// TODO - improve this
	m_textBag = world->GetMagicBag(world->GetTokenPool().AddToken("TEXT"));
}

void User::GetCurrentRoomNameToken (unsigned * outToken) const {
	if (m_room)
		*outToken = m_room->GetNameToken();
	else
		*outToken = 0;
}

void User::EnterConnectedRoom (unsigned directionIdToken) {
	if (!m_room)
		return;

	Room * target = m_room->FindConnection(directionIdToken);
	if (!target) {
		m_world->QueueEvent(m_scriptable, m_world->GetTokenPool().AddToken("EnterConnectedRoomFailed"), nullptr);
		return;
	}

	m_room = target;
	UpdateRoom();
}

void User::EnterRoom (unsigned roomIdToken) {
	m_room = m_worldState->roomNetwork->FindRoom(roomIdToken);
	UpdateRoom();
}

void User::SendRoomDescription (double) {
	assert(m_room != nullptr);

	std::cout << m_room->GetDescription() << std::endl;
}

void User::SendMessage (unsigned tokenId) {
	std::cout << m_textBag->GetLine(tokenId) << std::endl;
}

void User::PollInput (double) {
	std::string buffer;

	std::getline(std::cin, buffer);

	std::stringstream parser;
	parser << buffer;

	std::string command;
	parser >> command;

	if (command == "q" || command == "quit" || command == "exit") {
		m_worldState->alive = false;
		return;
	}

	if (command == "help") {
		std::string param;
		parser >> param;

		m_worldState->commands->DisplayHelp(param);

		return;
	}

	if (m_worldState->commands->DispatchCommandToWorld(command, parser, m_world, m_scriptable))
		return;

	std::cout << "What?" << std::endl;
}

void User::UpdateRoom () {
	auto * scopes = new ScopedPropertyBag();
	scopes->SetNamedBinding(m_world->GetTokenPool().AddToken("User"), m_scriptable);

	m_world->QueueEvent(m_room->GetScriptable(), m_world->GetTokenPool().AddToken("OnUserEnter"), scopes);
}

}

<commit_msg>Add blank line after room description text in FormulaMUD<commit_after>#include "Pch.h"

#include "User.h"
#include "WorldState.h"
#include "CommandTable.h"
#include "Room.h"

namespace Game {

User::User (ScriptWorld * world, Scriptable * boundScriptable, WorldState * worldState)
	: m_world(world),
	  m_scriptable(boundScriptable),
	  m_worldState(worldState),
	  m_room(nullptr)
{
	// TODO - improve this
	m_textBag = world->GetMagicBag(world->GetTokenPool().AddToken("TEXT"));
}

void User::GetCurrentRoomNameToken (unsigned * outToken) const {
	if (m_room)
		*outToken = m_room->GetNameToken();
	else
		*outToken = 0;
}

void User::EnterConnectedRoom (unsigned directionIdToken) {
	if (!m_room)
		return;

	Room * target = m_room->FindConnection(directionIdToken);
	if (!target) {
		m_world->QueueEvent(m_scriptable, m_world->GetTokenPool().AddToken("EnterConnectedRoomFailed"), nullptr);
		return;
	}

	m_room = target;
	UpdateRoom();
}

void User::EnterRoom (unsigned roomIdToken) {
	m_room = m_worldState->roomNetwork->FindRoom(roomIdToken);
	UpdateRoom();
}

void User::SendRoomDescription (double) {
	assert(m_room != nullptr);

	std::cout << m_room->GetDescription() << "\n" << std::endl;
}

void User::SendMessage (unsigned tokenId) {
	std::cout << m_textBag->GetLine(tokenId) << std::endl;
}

void User::PollInput (double) {
	std::string buffer;

	std::getline(std::cin, buffer);

	std::stringstream parser;
	parser << buffer;

	std::string command;
	parser >> command;

	if (command == "q" || command == "quit" || command == "exit") {
		m_worldState->alive = false;
		return;
	}

	if (command == "help") {
		std::string param;
		parser >> param;

		m_worldState->commands->DisplayHelp(param);

		return;
	}

	if (m_worldState->commands->DispatchCommandToWorld(command, parser, m_world, m_scriptable))
		return;

	std::cout << "What?" << std::endl;
}

void User::UpdateRoom () {
	auto * scopes = new ScopedPropertyBag();
	scopes->SetNamedBinding(m_world->GetTokenPool().AddToken("User"), m_scriptable);

	m_world->QueueEvent(m_room->GetScriptable(), m_world->GetTokenPool().AddToken("OnUserEnter"), scopes);
}

}

<|endoftext|>