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

#include <string.h>

#include "tbb/spin_rw_mutex.h"
#include "tbb/concurrent_hash_map.h"

#include "boost/multi_index_container.hpp"
#include "boost/lexical_cast.hpp"

#include "IECore/HashTable.h"
#include "IECore/InternedString.h"

namespace IECore
{

namespace Detail
{

typedef boost::multi_index::multi_index_container<
	std::string,
	boost::multi_index::indexed_by<
		boost::multi_index::hashed_unique<
			boost::multi_index::identity<std::string>,
			Hash<std::string>
		>
	>
> HashSet;

typedef HashSet::nth_index<0>::type Index;
typedef HashSet::nth_index_const_iterator<0>::type ConstIterator;
typedef tbb::spin_rw_mutex Mutex;

static HashSet *hashSet()
{
	static HashSet g_hashSet;
	return &g_hashSet;
}

static Mutex *mutex()
{
	static Detail::Mutex g_mutex;
	return &g_mutex;
}

struct StringCStringEqual
{
	bool operator()( const char *c, const std::string &s ) const
	{
		return strcmp( c, s.c_str() )==0;
	}
	bool operator()( const std::string &s, const char *c ) const
	{
		return strcmp( c, s.c_str() )==0;
	}
};

} // namespace Detail

const std::string *InternedString::internedString( const char *value )
{
	Detail::HashSet *hashSet = Detail::hashSet();
	Detail::Index &hashIndex = hashSet->get<0>();
	Detail::Mutex::scoped_lock lock( *Detail::mutex(), false ); // read-only lock
	Detail::HashSet::const_iterator it = hashIndex.find( value, Hash<const char *>(), Detail::StringCStringEqual() );
	if( it!=hashIndex.end() )
	{
		return &(*it);
	}
	else
	{
		lock.upgrade_to_writer();
		return &(*(hashSet->insert( std::string( value ) ).first ) );
	}
}

size_t InternedString::numUniqueStrings()
{
	Detail::Mutex::scoped_lock lock( *Detail::mutex(), false ); // read-only lock
	Detail::HashSet *hashSet = Detail::hashSet();
	return hashSet->size();
}

static InternedString g_emptyString("");

const InternedString &InternedString::emptyString()
{
	return g_emptyString;
}

// make sure we create the g_numbers map at load time.
static InternedString g_zero((int64_t)0);

const InternedString &InternedString::numberString( int64_t number )
{
	typedef tbb::concurrent_hash_map< int64_t, InternedString > NumbersMap;
	static NumbersMap *g_numbers = 0;
	if ( !g_numbers )
	{
		g_numbers = new NumbersMap;
	}
	NumbersMap::accessor it;
	if ( g_numbers->insert( it, number ) )
	{
		it->second = InternedString( boost::lexical_cast<std::string>( number ) );
	}
	return it->second;
}

std::ostream &operator << ( std::ostream &o, const InternedString &str )
{
	o << str.c_str();
	return o;
}

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

#include <string.h>

#include "tbb/spin_rw_mutex.h"
#include "tbb/concurrent_hash_map.h"

#include "boost/multi_index_container.hpp"
#include "boost/multi_index/hashed_index.hpp"
#include "boost/lexical_cast.hpp"

#include "IECore/InternedString.h"

namespace IECore
{

namespace Detail
{

// Hash for strings of various types.
// By overloading it for multiple types, we are able to do
// lookups into HashSet using any type as a key, and without
// needing to construct a temporary std::string when the type
// is a raw c string.
struct Hash
{

	// Dan Bernstein's original string hash
	size_t operator()( const char *s ) const
	{
		size_t hash = 5381;
		while( *s )
		{
			hash = ( ( hash << 5 ) + hash ) + *s++;
		}

		return hash;
	}

	size_t operator()( const std::string &s ) const
	{
		return (*this)( s.c_str() );
	}

};

// Equality operator between strings of various types.
// As above, this allows HashSet lookups to be performed
// using any type, without the overhead of constructing
// temporary std::strings.
struct Equal
{

	bool operator()( const std::string &s1, const std::string &s2 ) const
	{
		return s1 == s2;
	}

	bool operator()( const char *c, const std::string &s ) const
	{
		return strcmp( c, s.c_str() )==0;
	}

	bool operator()( const std::string &s, const char *c ) const
	{
		return strcmp( c, s.c_str() )==0;
	}

};

typedef boost::multi_index::multi_index_container<
	std::string,
	boost::multi_index::indexed_by<
		boost::multi_index::hashed_unique<
			boost::multi_index::identity<std::string>,
			Hash,
			Equal
		>
	>
> HashSet;

typedef HashSet::nth_index<0>::type Index;
typedef HashSet::nth_index_const_iterator<0>::type ConstIterator;
typedef tbb::spin_rw_mutex Mutex;

static HashSet *hashSet()
{
	static HashSet g_hashSet;
	return &g_hashSet;
}

static Mutex *mutex()
{
	static Detail::Mutex g_mutex;
	return &g_mutex;
}

} // namespace Detail

const std::string *InternedString::internedString( const char *value )
{
	Detail::HashSet *hashSet = Detail::hashSet();
	Detail::Index &hashIndex = hashSet->get<0>();
	Detail::Mutex::scoped_lock lock( *Detail::mutex(), false ); // read-only lock
	Detail::HashSet::const_iterator it = hashIndex.find( value );
	if( it!=hashIndex.end() )
	{
		return &(*it);
	}
	else
	{
		lock.upgrade_to_writer();
		return &(*(hashSet->insert( std::string( value ) ).first ) );
	}
}

size_t InternedString::numUniqueStrings()
{
	Detail::Mutex::scoped_lock lock( *Detail::mutex(), false ); // read-only lock
	Detail::HashSet *hashSet = Detail::hashSet();
	return hashSet->size();
}

static InternedString g_emptyString("");

const InternedString &InternedString::emptyString()
{
	return g_emptyString;
}

// make sure we create the g_numbers map at load time.
static InternedString g_zero((int64_t)0);

const InternedString &InternedString::numberString( int64_t number )
{
	typedef tbb::concurrent_hash_map< int64_t, InternedString > NumbersMap;
	static NumbersMap *g_numbers = 0;
	if ( !g_numbers )
	{
		g_numbers = new NumbersMap;
	}
	NumbersMap::accessor it;
	if ( g_numbers->insert( it, number ) )
	{
		it->second = InternedString( boost::lexical_cast<std::string>( number ) );
	}
	return it->second;
}

std::ostream &operator << ( std::ostream &o, const InternedString &str )
{
	o << str.c_str();
	return o;
}

} // namespace IECore
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreD3D11HardwareVertexBuffer.h"
#include "OgreD3D11HardwareBuffer.h"
#include "OgreD3D11Device.h"

namespace Ogre {

	//---------------------------------------------------------------------
	D3D11HardwareVertexBuffer::D3D11HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
		size_t numVertices, HardwareBuffer::Usage usage, D3D11Device & device,
		bool useSystemMemory, bool useShadowBuffer)
		: HardwareVertexBuffer(mgr, vertexSize, numVertices, usage, useSystemMemory, useShadowBuffer),
		  mBufferImpl(0)

	{
		// everything is done via internal generalisation
		mBufferImpl = new D3D11HardwareBuffer(D3D11HardwareBuffer::VERTEX_BUFFER,
			mSizeInBytes, mUsage, device, useSystemMemory, useShadowBuffer);

	}
	//---------------------------------------------------------------------
	D3D11HardwareVertexBuffer::~D3D11HardwareVertexBuffer()
	{
		SAFE_DELETE(mBufferImpl);
	}
	//---------------------------------------------------------------------
	void* D3D11HardwareVertexBuffer::lock(size_t offset, size_t length, LockOptions options)
	{
		return mBufferImpl->lock(offset, length, options);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::unlock(void)
	{
		mBufferImpl->unlock();
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::readData(size_t offset, size_t length, void* pDest)
	{
		mBufferImpl->readData(offset, length, pDest);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::writeData(size_t offset, size_t length, const void* pSource,
		bool discardWholeBuffer)
	{
		mBufferImpl->writeData(offset, length, pSource, discardWholeBuffer);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::copyData(HardwareBuffer& srcBuffer, size_t srcOffset,
		size_t dstOffset, size_t length, bool discardWholeBuffer)
	{
		// check if the other buffer is also a D3D11HardwareVertexBuffer
		if (srcBuffer.isSystemMemory())
		{
			// src is not not a D3D11HardwareVertexBuffer - use default copy
			HardwareBuffer::copyData(srcBuffer, srcOffset, dstOffset, length, discardWholeBuffer);
		}
		else
		{
			// src is a D3D11HardwareVertexBuffer use d3d11 optimized copy
			D3D11HardwareVertexBuffer& d3dBuf = static_cast<D3D11HardwareVertexBuffer&>(srcBuffer);

			mBufferImpl->copyData(*(d3dBuf.mBufferImpl), srcOffset, dstOffset, length, discardWholeBuffer);
		}
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::isLocked(void) const
	{
		return mBufferImpl->isLocked();
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::releaseIfDefaultPool(void)
	{
		/*		if (mD3DPool == D3DPOOL_DEFAULT)
		{
		SAFE_RELEASE(mlpD3DBuffer);
		return true;
		}
		return false;
		*/
		return true;
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::recreateIfDefaultPool(D3D11Device & device)
	{
		/*	if (mD3DPool == D3DPOOL_DEFAULT)
		{
		// Create the Index buffer
		HRESULT hr = device->CreateIndexBuffer(
		static_cast<UINT>(mSizeInBytes),
		D3D11Mappings::get(mUsage),
		D3D11Mappings::get(mIndexType),
		mD3DPool,
		&mlpD3DBuffer,
		NULL
		);

		if (FAILED(hr))
		{
		String msg = DXGetErrorDescription(hr);
		OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
		"Cannot create D3D11 Index buffer: " + msg,
		"D3D11HardwareVertexBuffer::D3D11HardwareVertexBuffer");
		}

		return true;
		}
		return false;
		*/
		return true;
	}
	//---------------------------------------------------------------------
	ID3D11Buffer * D3D11HardwareVertexBuffer::getD3DVertexBuffer( void ) const
	{
		return mBufferImpl->getD3DBuffer();
	}
	//---------------------------------------------------------------------

}

<commit_msg>D3D11 render system: Fixed a comment typo.<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2009 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#include "OgreD3D11HardwareVertexBuffer.h"
#include "OgreD3D11HardwareBuffer.h"
#include "OgreD3D11Device.h"

namespace Ogre {

	//---------------------------------------------------------------------
	D3D11HardwareVertexBuffer::D3D11HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
		size_t numVertices, HardwareBuffer::Usage usage, D3D11Device & device,
		bool useSystemMemory, bool useShadowBuffer)
		: HardwareVertexBuffer(mgr, vertexSize, numVertices, usage, useSystemMemory, useShadowBuffer),
		  mBufferImpl(0)

	{
		// everything is done via internal generalisation
		mBufferImpl = new D3D11HardwareBuffer(D3D11HardwareBuffer::VERTEX_BUFFER,
			mSizeInBytes, mUsage, device, useSystemMemory, useShadowBuffer);

	}
	//---------------------------------------------------------------------
	D3D11HardwareVertexBuffer::~D3D11HardwareVertexBuffer()
	{
		SAFE_DELETE(mBufferImpl);
	}
	//---------------------------------------------------------------------
	void* D3D11HardwareVertexBuffer::lock(size_t offset, size_t length, LockOptions options)
	{
		return mBufferImpl->lock(offset, length, options);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::unlock(void)
	{
		mBufferImpl->unlock();
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::readData(size_t offset, size_t length, void* pDest)
	{
		mBufferImpl->readData(offset, length, pDest);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::writeData(size_t offset, size_t length, const void* pSource,
		bool discardWholeBuffer)
	{
		mBufferImpl->writeData(offset, length, pSource, discardWholeBuffer);
	}
	//---------------------------------------------------------------------
	void D3D11HardwareVertexBuffer::copyData(HardwareBuffer& srcBuffer, size_t srcOffset,
		size_t dstOffset, size_t length, bool discardWholeBuffer)
	{
		// check if the other buffer is also a D3D11HardwareVertexBuffer
		if (srcBuffer.isSystemMemory())
		{
			// src is not a D3D11HardwareVertexBuffer - use default copy
			HardwareBuffer::copyData(srcBuffer, srcOffset, dstOffset, length, discardWholeBuffer);
		}
		else
		{
			// src is a D3D11HardwareVertexBuffer use d3d11 optimized copy
			D3D11HardwareVertexBuffer& d3dBuf = static_cast<D3D11HardwareVertexBuffer&>(srcBuffer);

			mBufferImpl->copyData(*(d3dBuf.mBufferImpl), srcOffset, dstOffset, length, discardWholeBuffer);
		}
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::isLocked(void) const
	{
		return mBufferImpl->isLocked();
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::releaseIfDefaultPool(void)
	{
		/*		if (mD3DPool == D3DPOOL_DEFAULT)
		{
		SAFE_RELEASE(mlpD3DBuffer);
		return true;
		}
		return false;
		*/
		return true;
	}
	//---------------------------------------------------------------------
	bool D3D11HardwareVertexBuffer::recreateIfDefaultPool(D3D11Device & device)
	{
		/*	if (mD3DPool == D3DPOOL_DEFAULT)
		{
		// Create the Index buffer
		HRESULT hr = device->CreateIndexBuffer(
		static_cast<UINT>(mSizeInBytes),
		D3D11Mappings::get(mUsage),
		D3D11Mappings::get(mIndexType),
		mD3DPool,
		&mlpD3DBuffer,
		NULL
		);

		if (FAILED(hr))
		{
		String msg = DXGetErrorDescription(hr);
		OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
		"Cannot create D3D11 Index buffer: " + msg,
		"D3D11HardwareVertexBuffer::D3D11HardwareVertexBuffer");
		}

		return true;
		}
		return false;
		*/
		return true;
	}
	//---------------------------------------------------------------------
	ID3D11Buffer * D3D11HardwareVertexBuffer::getD3DVertexBuffer( void ) const
	{
		return mBufferImpl->getD3DBuffer();
	}
	//---------------------------------------------------------------------

}

<|endoftext|>


<commit_before>/*
 -----------------------------------------------------------------------------
 This source file is part of OGRE
 (Object-oriented Graphics Rendering Engine)
 For the latest info, see http://www.ogre3d.org/

 Copyright (c) 2000-2014 Torus Knot Software Ltd

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 -----------------------------------------------------------------------------
 */

#include "OgreGLSLESProgramCommon.h"
#include "OgreGLSLESProgram.h"
#include "OgreGpuProgramManager.h"
#include "OgreGLUtil.h"
#include "OgreGLES2RenderSystem.h"
#include "OgreRoot.h"
#include "OgreGLNativeSupport.h"

namespace Ogre {

    //-----------------------------------------------------------------------
    GLSLESProgramCommon::GLSLESProgramCommon(const GLShaderList& shaders)
    : GLSLProgramCommon(shaders)
    {
    }

    void GLSLESProgramCommon::bindFixedAttributes(GLuint program)
    {
        GLint maxAttribs = Root::getSingleton().getRenderSystem()->getCapabilities()->getNumVertexAttributes();

        size_t numAttribs = sizeof(msCustomAttributes) / sizeof(CustomAttribute);
        for (size_t i = 0; i < numAttribs; ++i)
        {
            const CustomAttribute& a = msCustomAttributes[i];
            if (a.attrib < maxAttribs)
            {

                OGRE_CHECK_GL_ERROR(glBindAttribLocation(program, a.attrib, a.name));
            }
        }
    }

    //-----------------------------------------------------------------------
    bool GLSLESProgramCommon::getMicrocodeFromCache(uint32 id, GLuint programHandle)
    {
        if (!GpuProgramManager::canGetCompiledShaderBuffer())
            return false;

        if (!GpuProgramManager::getSingleton().isMicrocodeAvailableInCache(id))
            return false;

        GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(id);

        // turns out we need this param when loading
        GLenum binaryFormat = 0;

        cacheMicrocode->seek(0);

        // get size of binary
        cacheMicrocode->read(&binaryFormat, sizeof(GLenum));

        if(!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_CAN_GET_COMPILED_SHADER_BUFFER))
            return false;

        GLint binaryLength = static_cast<GLint>(cacheMicrocode->size() - sizeof(GLenum));

        // load binary
        OGRE_CHECK_GL_ERROR(glProgramBinaryOES(programHandle,
                           binaryFormat,
                           cacheMicrocode->getCurrentPtr(),
                           binaryLength));

        GLint success = 0;
        OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &success));

        return success;
    }
    void GLSLESProgramCommon::_writeToCache(uint32 id, GLuint programHandle)
    {
        if(!GpuProgramManager::canGetCompiledShaderBuffer())
            return;

        if(!GpuProgramManager::getSingleton().getSaveMicrocodesToCache())
            return;

        // Add to the microcode to the cache
        // Get buffer size
        GLint binaryLength = 0;
        OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength));

        // Create microcode
        GpuProgramManager::Microcode newMicrocode =
            GpuProgramManager::getSingleton().createMicrocode(static_cast<uint32>(binaryLength + sizeof(GLenum)));

        // Get binary
        OGRE_CHECK_GL_ERROR(glGetProgramBinaryOES(programHandle, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(),
                                                  newMicrocode->getPtr() + sizeof(GLenum)));

        // Add to the microcode to the cache
        GpuProgramManager::getSingleton().addMicrocodeToCache(id, newMicrocode);
    }

#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
    void GLSLESProgramCommon::notifyOnContextLost()
    {
        mLinked = false;
        mUniformRefsBuilt = false;
        for(auto s : mShaders)
        {
            if(s) s->getUniformCache()->clearCache();
        }
    }

    void GLSLESProgramCommon::notifyOnContextReset()
    {
        activate();
    }
#endif
} // namespace Ogre
<commit_msg>GLES2: iOS - suppress attribute warnings<commit_after>/*
 -----------------------------------------------------------------------------
 This source file is part of OGRE
 (Object-oriented Graphics Rendering Engine)
 For the latest info, see http://www.ogre3d.org/

 Copyright (c) 2000-2014 Torus Knot Software Ltd

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 -----------------------------------------------------------------------------
 */

#include "OgreGLSLESProgramCommon.h"
#include "OgreGLSLESProgram.h"
#include "OgreGpuProgramManager.h"
#include "OgreGLUtil.h"
#include "OgreGLES2RenderSystem.h"
#include "OgreRoot.h"
#include "OgreGLNativeSupport.h"

namespace Ogre {

    //-----------------------------------------------------------------------
    GLSLESProgramCommon::GLSLESProgramCommon(const GLShaderList& shaders)
    : GLSLProgramCommon(shaders)
    {
    }

    void GLSLESProgramCommon::bindFixedAttributes(GLuint program)
    {
        GLint maxAttribs = Root::getSingleton().getRenderSystem()->getCapabilities()->getNumVertexAttributes();

#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
        // must query active attributes on OSX to avoid warning spam
        OGRE_CHECK_GL_ERROR(glLinkProgram( program ));
#endif

        size_t numAttribs = sizeof(msCustomAttributes) / sizeof(CustomAttribute);
        for (size_t i = 0; i < numAttribs; ++i)
        {
            const CustomAttribute& a = msCustomAttributes[i];
            if (a.attrib < maxAttribs)
            {
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS
                if(glGetAttribLocation(program, a.name) == -1) continue;
#endif
                OGRE_CHECK_GL_ERROR(glBindAttribLocation(program, a.attrib, a.name));
            }
        }
    }

    //-----------------------------------------------------------------------
    bool GLSLESProgramCommon::getMicrocodeFromCache(uint32 id, GLuint programHandle)
    {
        if (!GpuProgramManager::canGetCompiledShaderBuffer())
            return false;

        if (!GpuProgramManager::getSingleton().isMicrocodeAvailableInCache(id))
            return false;

        GpuProgramManager::Microcode cacheMicrocode = GpuProgramManager::getSingleton().getMicrocodeFromCache(id);

        // turns out we need this param when loading
        GLenum binaryFormat = 0;

        cacheMicrocode->seek(0);

        // get size of binary
        cacheMicrocode->read(&binaryFormat, sizeof(GLenum));

        if(!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_CAN_GET_COMPILED_SHADER_BUFFER))
            return false;

        GLint binaryLength = static_cast<GLint>(cacheMicrocode->size() - sizeof(GLenum));

        // load binary
        OGRE_CHECK_GL_ERROR(glProgramBinaryOES(programHandle,
                           binaryFormat,
                           cacheMicrocode->getCurrentPtr(),
                           binaryLength));

        GLint success = 0;
        OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &success));

        return success;
    }
    void GLSLESProgramCommon::_writeToCache(uint32 id, GLuint programHandle)
    {
        if(!GpuProgramManager::canGetCompiledShaderBuffer())
            return;

        if(!GpuProgramManager::getSingleton().getSaveMicrocodesToCache())
            return;

        // Add to the microcode to the cache
        // Get buffer size
        GLint binaryLength = 0;
        OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength));

        // Create microcode
        GpuProgramManager::Microcode newMicrocode =
            GpuProgramManager::getSingleton().createMicrocode(static_cast<uint32>(binaryLength + sizeof(GLenum)));

        // Get binary
        OGRE_CHECK_GL_ERROR(glGetProgramBinaryOES(programHandle, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(),
                                                  newMicrocode->getPtr() + sizeof(GLenum)));

        // Add to the microcode to the cache
        GpuProgramManager::getSingleton().addMicrocodeToCache(id, newMicrocode);
    }

#if OGRE_PLATFORM == OGRE_PLATFORM_ANDROID || OGRE_PLATFORM == OGRE_PLATFORM_EMSCRIPTEN
    void GLSLESProgramCommon::notifyOnContextLost()
    {
        mLinked = false;
        mUniformRefsBuilt = false;
        for(auto s : mShaders)
        {
            if(s) s->getUniformCache()->clearCache();
        }
    }

    void GLSLESProgramCommon::notifyOnContextReset()
    {
        activate();
    }
#endif
} // namespace Ogre
<|endoftext|>


<commit_before>#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <uuid/uuid.h>
#include <vector>
#include <wchar.h>

#include <scxcorelib/scxcmn.h>
#include <scxcorelib/scxprocess.h>
#include <scxcorelib/stringaid.h>
#include <testutils/scxunit.h>
#include <testutils/providertestutils.h>

#include "Container_ImageInventory_Class_Provider.h"
#include "cjson/cJSON.h"
#include "TestScriptPath.h"

using namespace std;
using namespace SCXCoreLib;

class ImageInventoryTest : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE(ImageInventoryTest);
	CPPUNIT_TEST(TestEnumerateInstances);
	CPPUNIT_TEST(TestEnumerateVerifyAllValues);
	CPPUNIT_TEST(TestRunContainer);
	CPPUNIT_TEST(TestRunFailedContainer);
	CPPUNIT_TEST_SUITE_END();

private:
	vector<string> containers;

	static string NewGuid()
	{
		uuid_t uuid;
		uuid_generate_random(uuid);
		char s[37];
		uuid_unparse(uuid, s);
		return s;
	}

	static string RunCommand(const char* command)
	{
		istringstream processInput;
		ostringstream processOutput;
		ostringstream processErr;

		CPPUNIT_ASSERT(!SCXProcess::Run(StrFromMultibyte(string(command)), processInput, processOutput, processErr, 0));
		CPPUNIT_ASSERT_EQUAL(processErr.str(), string());

		return processOutput.str();
	}

public:
	void setUp()
	{
		// Get some images to use
		fputc('\n', stdout);
		RunCommand("docker pull hello-world");
		RunCommand("docker pull centos");
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ImageInventory/*");
	}

	void tearDown()
	{
		char command[128];

		// Remove the containers that were started by the tests
		for (unsigned i = 0; i < containers.size(); i++)
		{
			sprintf(command, "docker rm -f %s", containers[i].c_str());
			RunCommand(command);
		}

		containers.clear();
	}

protected:
	void TestEnumerateInstances()
	{
		wstring errMsg;
		TestableContext context;

		vector<wstring> m_keyNames;
		m_keyNames.push_back(L"InstanceID");

		// Remove cached state
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ContainerInventory/*");

		// Enumerate provider
		StandardTestEnumerateInstances<mi::Container_ImageInventory_Class_Provider>(m_keyNames, context, CALL_LOCATION(errMsg));

		// Get images using command line
		CPPUNIT_ASSERT(!system("docker images -q --no-trunc > /tmp/docker_image_ids.txt"));

		FILE* idFile = fopen("/tmp/docker_image_ids.txt", "r");
		CPPUNIT_ASSERT(idFile);

		wchar_t id[65];
		set<wstring> allIds;

		// Full image IDs (one per line)
		while (fwscanf(idFile, L"%ls", id) != EOF)
		{
			allIds.insert(wstring(id));
		}

		fclose(idFile);
		remove("/tmp/docker_image_ids.txt");

		CPPUNIT_ASSERT_EQUAL(allIds.size(), context.Size());

		for (unsigned i = 0; i < context.Size(); ++i)
		{
			// Verify the InstanceID
			CPPUNIT_ASSERT(allIds.count(context[i].GetKey(L"InstanceID", CALL_LOCATION(errMsg))));
		}
	}

	void TestEnumerateVerifyAllValues()
	{
		wstring errMsg;
		TestableContext context;

		vector<wstring> m_keyNames;
		m_keyNames.push_back(L"InstanceID");

		// Remove cached state
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ContainerInventory/*");

		// Enumerate provider
		StandardTestEnumerateInstances<mi::Container_ImageInventory_Class_Provider>(m_keyNames, context, CALL_LOCATION(errMsg));

		// Get image inventory using a script
		char command[256];
		sprintf(command, "python %sImageInventory.py > /tmp/docker_image_inventory.txt", TEST_SCRIPT_PATH);
		CPPUNIT_ASSERT(!system(command));

		FILE* imageFile = fopen("/tmp/docker_image_inventory.txt", "r");
		CPPUNIT_ASSERT(imageFile);

		char buffer[1024];
		vector<cJSON*> images;

		while (fgets(buffer, 1023, imageFile))
		{
			images.push_back(cJSON_Parse(buffer));
		}

		fclose(imageFile);
		remove("/tmp/docker_image_inventory.txt");

		// Should have same number of images
		CPPUNIT_ASSERT_EQUAL(images.size(), context.Size());

		wchar_t currentId[66];
		int imageCount = 0;

		// Verify every field of every object
		for (unsigned i = 0; i < images.size(); i++)
		{
			bool flag = false;
			mbstowcs(currentId, cJSON_GetObjectItem(images[i], "InstanceID")->valuestring, 65);

			for (unsigned j = 0; !flag && j < context.Size(); j++)
			{
				if (!context[j].GetProperty(L"InstanceID", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)).compare(wstring(currentId)))
				{
					wchar_t temp[512];
					unsigned count = 0;

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "Image")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"Image", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "Repository")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"Repository", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "ImageTag")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"ImageTag", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "Computer")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"Computer", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "ImageSize")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"ImageSize", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "VirtualSize")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"VirtualSize", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Running")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Running", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Stopped")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Stopped", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Failed")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Failed", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Paused")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Paused", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Total")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Total", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					flag = true;
					imageCount += 1;
				}
			}

			cJSON_Delete(images[i]);
		}

		// Ensure all objects were validated
		CPPUNIT_ASSERT_EQUAL(imageCount, context.Size());
	}

	void TestRunContainer()
	{
		wstring errMsg;
		TestableContext context;

		vector<wstring> m_keyNames;
		m_keyNames.push_back(L"InstanceID");

		// Remove cached state
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ContainerInventory/*");

		char containerName[64];
		strcpy(containerName, NewGuid().c_str());
		containers.push_back(string(containerName));
		char command[128];
		sprintf(command, "docker run --name=%s hello-world", containerName);

		CPPUNIT_ASSERT(!system(command));
		sleep(5);

		bool flag = false;

		// Enumerate provider
		StandardTestEnumerateInstances<mi::Container_ImageInventory_Class_Provider>(m_keyNames, context, CALL_LOCATION(errMsg));

		for (unsigned i = 0; !flag && i < context.Size(); ++i)
		{
			if (!context[i].GetProperty(L"Image", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)).compare(L"hello-world"))
			{
				// Checke that the number of stopped containers is not 0
				CPPUNIT_ASSERT(context[i].GetProperty(L"Stopped", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));
				flag = true;
			}
		}
	}

	void TestRunFailedContainer()
	{
		wstring errMsg;
		TestableContext context;

		vector<wstring> m_keyNames;
		m_keyNames.push_back(L"InstanceID");

		// Remove cached state
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ContainerInventory/*");

		char containerName[64];
		strcpy(containerName, NewGuid().c_str());
		containers.push_back(string(containerName));
		char command[128];
		sprintf(command, "docker run --name=%s centos false", containerName);

		CPPUNIT_ASSERT(system(command));
		sleep(5);

		bool flag = false;

		// Enumerate provider
		StandardTestEnumerateInstances<mi::Container_ImageInventory_Class_Provider>(m_keyNames, context, CALL_LOCATION(errMsg));

		for (unsigned i = 0; !flag && i < context.Size(); ++i)
		{
			if (!context[i].GetProperty(L"Image", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)).compare(L"centos"))
			{
				// Check that the number of failed containers is not 0
				CPPUNIT_ASSERT(context[i].GetProperty(L"Failed", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));
				flag = true;
			}
		}
	}

};

CPPUNIT_TEST_SUITE_REGISTRATION(ImageInventoryTest);<commit_msg>Fix image inventory unit test: Buffer for ID was too short.<commit_after>#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <uuid/uuid.h>
#include <vector>
#include <wchar.h>

#include <scxcorelib/scxcmn.h>
#include <scxcorelib/scxprocess.h>
#include <scxcorelib/stringaid.h>
#include <testutils/scxunit.h>
#include <testutils/providertestutils.h>

#include "Container_ImageInventory_Class_Provider.h"
#include "cjson/cJSON.h"
#include "TestScriptPath.h"

using namespace std;
using namespace SCXCoreLib;

class ImageInventoryTest : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE(ImageInventoryTest);
	CPPUNIT_TEST(TestEnumerateInstances);
	CPPUNIT_TEST(TestEnumerateVerifyAllValues);
	CPPUNIT_TEST(TestRunContainer);
	CPPUNIT_TEST(TestRunFailedContainer);
	CPPUNIT_TEST_SUITE_END();

private:
	vector<string> containers;

	static string NewGuid()
	{
		uuid_t uuid;
		uuid_generate_random(uuid);
		char s[37];
		uuid_unparse(uuid, s);
		return s;
	}

	static string RunCommand(const char* command)
	{
		istringstream processInput;
		ostringstream processOutput;
		ostringstream processErr;

		CPPUNIT_ASSERT(!SCXProcess::Run(StrFromMultibyte(string(command)), processInput, processOutput, processErr, 0));
		CPPUNIT_ASSERT_EQUAL(processErr.str(), string());

		return processOutput.str();
	}

public:
	void setUp()
	{
		// Get some images to use
		fputc('\n', stdout);
		RunCommand("docker pull hello-world");
		RunCommand("docker pull centos");
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ImageInventory/*");
	}

	void tearDown()
	{
		char command[128];

		// Remove the containers that were started by the tests
		for (unsigned i = 0; i < containers.size(); i++)
		{
			sprintf(command, "docker rm -f %s", containers[i].c_str());
			RunCommand(command);
		}

		containers.clear();
	}

protected:
	void TestEnumerateInstances()
	{
		wstring errMsg;
		TestableContext context;

		vector<wstring> m_keyNames;
		m_keyNames.push_back(L"InstanceID");

		// Remove cached state
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ContainerInventory/*");

		// Enumerate provider
		StandardTestEnumerateInstances<mi::Container_ImageInventory_Class_Provider>(m_keyNames, context, CALL_LOCATION(errMsg));

		// Get images using command line
		CPPUNIT_ASSERT(!system("docker images -q --no-trunc > /tmp/docker_image_ids.txt"));

		FILE* idFile = fopen("/tmp/docker_image_ids.txt", "r");
		CPPUNIT_ASSERT(idFile);

		wchar_t id[65];
		set<wstring> allIds;

		// Full image IDs (one per line)
		while (fwscanf(idFile, L"%ls", id) != EOF)
		{
			allIds.insert(wstring(id));
		}

		fclose(idFile);
		remove("/tmp/docker_image_ids.txt");

		CPPUNIT_ASSERT_EQUAL(allIds.size(), context.Size());

		for (unsigned i = 0; i < context.Size(); ++i)
		{
			// Verify the InstanceID
			CPPUNIT_ASSERT(allIds.count(context[i].GetKey(L"InstanceID", CALL_LOCATION(errMsg))));
		}
	}

	void TestEnumerateVerifyAllValues()
	{
		wstring errMsg;
		TestableContext context;

		vector<wstring> m_keyNames;
		m_keyNames.push_back(L"InstanceID");

		// Remove cached state
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ContainerInventory/*");

		// Enumerate provider
		StandardTestEnumerateInstances<mi::Container_ImageInventory_Class_Provider>(m_keyNames, context, CALL_LOCATION(errMsg));

		// Get image inventory using a script
		char command[256];
		sprintf(command, "python %sImageInventory.py > /tmp/docker_image_inventory.txt", TEST_SCRIPT_PATH);
		CPPUNIT_ASSERT(!system(command));

		FILE* imageFile = fopen("/tmp/docker_image_inventory.txt", "r");
		CPPUNIT_ASSERT(imageFile);

		char buffer[1024];
		vector<cJSON*> images;

		while (fgets(buffer, 1023, imageFile))
		{
			images.push_back(cJSON_Parse(buffer));
		}

		fclose(imageFile);
		remove("/tmp/docker_image_inventory.txt");

		// Should have same number of images
		CPPUNIT_ASSERT_EQUAL(images.size(), context.Size());

		wchar_t currentId[128];
		int imageCount = 0;

		// Verify every field of every object
		for (unsigned i = 0; i < images.size(); i++)
		{
			bool flag = false;
			int rc = mbstowcs(currentId, cJSON_GetObjectItem(images[i], "InstanceID")->valuestring, (sizeof(currentId)/sizeof(currentId[0])) - 1);
			if (rc > 0 && rc < sizeof(currentId)/sizeof(currentId[0])) currentId[rc] = 0;

			for (unsigned j = 0; !flag && j < context.Size(); j++)
			{
				if (!context[j].GetProperty(L"InstanceID", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)).compare(wstring(currentId)))
				{
					wchar_t temp[512];
					unsigned count = 0;

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "Image")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"Image", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "Repository")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"Repository", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "ImageTag")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"ImageTag", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "Computer")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"Computer", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "ImageSize")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"ImageSize", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					mbstowcs(temp, cJSON_GetObjectItem(images[i], "VirtualSize")->valuestring, 511);
					CPPUNIT_ASSERT_EQUAL(wstring(temp), context[j].GetProperty(L"VirtualSize", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Running")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Running", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Stopped")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Stopped", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Failed")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Failed", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Paused")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Paused", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					count = cJSON_GetObjectItem(images[i], "Total")->valueint;
					CPPUNIT_ASSERT_EQUAL(count, context[j].GetProperty(L"Total", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));

					flag = true;
					imageCount += 1;
				}
			}

			cJSON_Delete(images[i]);
		}

		// Ensure all objects were validated
		CPPUNIT_ASSERT_EQUAL(imageCount, context.Size());
	}

	void TestRunContainer()
	{
		wstring errMsg;
		TestableContext context;

		vector<wstring> m_keyNames;
		m_keyNames.push_back(L"InstanceID");

		// Remove cached state
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ContainerInventory/*");

		char containerName[64];
		strcpy(containerName, NewGuid().c_str());
		containers.push_back(string(containerName));
		char command[128];
		sprintf(command, "docker run --name=%s hello-world", containerName);

		CPPUNIT_ASSERT(!system(command));
		sleep(5);

		bool flag = false;

		// Enumerate provider
		StandardTestEnumerateInstances<mi::Container_ImageInventory_Class_Provider>(m_keyNames, context, CALL_LOCATION(errMsg));

		for (unsigned i = 0; !flag && i < context.Size(); ++i)
		{
			if (!context[i].GetProperty(L"Image", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)).compare(L"hello-world"))
			{
				// Checke that the number of stopped containers is not 0
				CPPUNIT_ASSERT(context[i].GetProperty(L"Stopped", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));
				flag = true;
			}
		}
	}

	void TestRunFailedContainer()
	{
		wstring errMsg;
		TestableContext context;

		vector<wstring> m_keyNames;
		m_keyNames.push_back(L"InstanceID");

		// Remove cached state
		RunCommand("rm -f /var/opt/microsoft/docker-cimprov/state/ContainerInventory/*");

		char containerName[64];
		strcpy(containerName, NewGuid().c_str());
		containers.push_back(string(containerName));
		char command[128];
		sprintf(command, "docker run --name=%s centos false", containerName);

		CPPUNIT_ASSERT(system(command));
		sleep(5);

		bool flag = false;

		// Enumerate provider
		StandardTestEnumerateInstances<mi::Container_ImageInventory_Class_Provider>(m_keyNames, context, CALL_LOCATION(errMsg));

		for (unsigned i = 0; !flag && i < context.Size(); ++i)
		{
			if (!context[i].GetProperty(L"Image", CALL_LOCATION(errMsg)).GetValue_MIString(CALL_LOCATION(errMsg)).compare(L"centos"))
			{
				// Check that the number of failed containers is not 0
				CPPUNIT_ASSERT(context[i].GetProperty(L"Failed", CALL_LOCATION(errMsg)).GetValue_MIUint32(CALL_LOCATION(errMsg)));
				flag = true;
			}
		}
	}

};

CPPUNIT_TEST_SUITE_REGISTRATION(ImageInventoryTest);<|endoftext|>


<commit_before>#include "../../battery.h"
#include "../../../utils.h"

#define BATTERY_BASE_DIR "/proc/acpi/battery/"

AspectsRegister Battery::aspectsRegister("Battery", getInstance());

Battery * Battery::battery = 0;

Battery * Battery::getInstance() {
	if ( battery == 0 )
		battery = new Battery();
	return battery;
}

vector<string> Battery::getComponents()
{
	vector<string> components;
	components.insert(components.end(), "_default");
	components.insert(components.end(), "_active");

	string res = Utils::exec(string("ls -1 ") + BATTERY_BASE_DIR);

	int pos, lastpos = 0;

	while ( (pos = res.find('\n',lastpos)) != string::npos)
	{
		components.insert(components.end(), res.substr(lastpos, pos-lastpos).c_str());
		lastpos = pos+1;
	}

	return components;
}

bool Battery::isSupported(string * property)
{
	return true;
}

string Battery::getPropertyValue(string * property, string * component)
{
	if (*property == "batteryLevel")
		return batteryLevel(*component);

	if (*property == "batteryBeingCharged")
		return batteryBeingCharged(*component);

	// TODO: instead trigger the error callback with DOMError of type InvalidAccessError (or abort if no error callback defined)
	return "Invalid property";
}

string Battery::batteryLevel(string batteryName)
{
	string line, tmp;
	int lastFullCapacity, remainingCapacity;

	if (batteryName[0] == '_')
		batteryName = getComponents()[2];

	string batteryInfoFile(BATTERY_BASE_DIR + batteryName + "/info");
	string batteryStateFile(BATTERY_BASE_DIR + batteryName + "/state");
	char* res = new char[7];

	ifstream info(batteryInfoFile.c_str());

	while(getline(info, line))
	{
		if (line.find("last full capacity") != string::npos)
		{
			stringstream linestream(line);
			linestream >> tmp >> tmp >> tmp >> lastFullCapacity >> tmp;
			break;
		}
	}

	ifstream state(batteryStateFile.c_str());

	while(getline(state, line))
	{
		if (line.find("remaining capacity") != string::npos)
		{
			stringstream linestream(line);
			linestream >> tmp >> tmp >> remainingCapacity >> tmp;
			break;
		}
	}

	sprintf(res, "%.2f", (float)remainingCapacity / lastFullCapacity * 100);

//	cout << res;
	return string(res);
}

string Battery::batteryBeingCharged(string batteryName)
{
	string line, tmp;
	string chargingState;

	if (batteryName[0] == '_')
		batteryName = getComponents()[2];

	string batteryStateFile(BATTERY_BASE_DIR + batteryName + "/state");

	ifstream state(batteryStateFile.c_str());

	while(getline(state, line))
	{
		if (line.find("charging state") != string::npos)
		{
			stringstream linestream(line);
			linestream >> tmp >> tmp >> chargingState;
			break;
		}
	}

	return chargingState == "charging" ? "true" : "false";
}
<commit_msg>Fixed bug including missing libraries<commit_after>#include "../../battery.h"
#include "../../../utils.h"

#include <iostream>
#include <fstream>
#include <sstream>

#define BATTERY_BASE_DIR "/proc/acpi/battery/"

AspectsRegister Battery::aspectsRegister("Battery", getInstance());

Battery * Battery::battery = 0;

Battery * Battery::getInstance() {
	if ( battery == 0 )
		battery = new Battery();
	return battery;
}

vector<string> Battery::getComponents()
{
	vector<string> components;
	components.insert(components.end(), "_default");
	components.insert(components.end(), "_active");

	string res = Utils::exec(string("ls -1 ") + BATTERY_BASE_DIR);

	int pos, lastpos = 0;

	while ( (pos = res.find('\n',lastpos)) != string::npos)
	{
		components.insert(components.end(), res.substr(lastpos, pos-lastpos).c_str());
		lastpos = pos+1;
	}

	return components;
}

bool Battery::isSupported(string * property)
{
	return true;
}

string Battery::getPropertyValue(string * property, string * component)
{
	if (*property == "batteryLevel")
		return batteryLevel(*component);

	if (*property == "batteryBeingCharged")
		return batteryBeingCharged(*component);

	// TODO: instead trigger the error callback with DOMError of type InvalidAccessError (or abort if no error callback defined)
	return "Invalid property";
}

string Battery::batteryLevel(string batteryName)
{
	string line, tmp;
	int lastFullCapacity, remainingCapacity;

	if (batteryName[0] == '_')
		batteryName = getComponents()[2];

	string batteryInfoFile(BATTERY_BASE_DIR + batteryName + "/info");
	string batteryStateFile(BATTERY_BASE_DIR + batteryName + "/state");
	char* res = new char[7];

	ifstream info(batteryInfoFile.c_str());

	while(getline(info, line))
	{
		if (line.find("last full capacity") != string::npos)
		{
			stringstream linestream(line);
			linestream >> tmp >> tmp >> tmp >> lastFullCapacity >> tmp;
			break;
		}
	}

	ifstream state(batteryStateFile.c_str());

	while(getline(state, line))
	{
		if (line.find("remaining capacity") != string::npos)
		{
			stringstream linestream(line);
			linestream >> tmp >> tmp >> remainingCapacity >> tmp;
			break;
		}
	}

	sprintf(res, "%.2f", (float)remainingCapacity / lastFullCapacity * 100);

//	cout << res;
	return string(res);
}

string Battery::batteryBeingCharged(string batteryName)
{
	string line, tmp;
	string chargingState;

	if (batteryName[0] == '_')
		batteryName = getComponents()[2];

	string batteryStateFile(BATTERY_BASE_DIR + batteryName + "/state");

	ifstream state(batteryStateFile.c_str());

	while(getline(state, line))
	{
		if (line.find("charging state") != string::npos)
		{
			stringstream linestream(line);
			linestream >> tmp >> tmp >> chargingState;
			break;
		}
	}

	return chargingState == "charging" ? "true" : "false";
}
<|endoftext|>


<commit_before>// Copyright (c) 2014 Dims dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "addressToCoins.h"

#include <boost/foreach.hpp>
//#include <stdint.h>

namespace tracker
{

template <class K, class T, char _prefix >
class CBatchWrite
{
public:
	void insert( K _key, T _object )
	{
		m_batch.Write( std::make_pair(_prefix, _key), _object );
	}
	CLevelDBBatch & getBatch(){ return m_batch; }
private:
	CLevelDBBatch m_batch;
};

CAddressToCoinsDatabase::CAddressToCoinsDatabase(size_t nCacheSize, bool fMemory, bool fWipe)
: db(GetDataDir(common::AppType::Tracker) / "addressTocoins",
	nCacheSize,
	fMemory,
	fWipe)
{
}

bool
CAddressToCoinsDatabase::getCoinsAmount(const uint160 &_keyId, uint64_t & _amount )
{
	return db.Read( std::make_pair('a', _keyId), _amount );
}

bool
CAddressToCoinsDatabase::setCoinsAmount(uint160 const &_keyId, uint64_t const _amount)
{
	return db.Write( std::make_pair('a', _keyId), _amount );
}

bool
CAddressToCoinsDatabase::getCoin(CKeyType const &_keyId, uint256 &coins)
{
	return db.Read( std::make_pair('c', _keyId), coins );
}

bool
CAddressToCoinsDatabase::setCoin(CKeyType const &_keyId, uint256 const &coins)
{
	return db.Write( std::make_pair('c', _keyId), coins );
}

bool
CAddressToCoinsDatabase::eraseCoin( uint256 const &_keyId )
{
	return db.Erase( std::make_pair('c', _keyId) );
}

bool
CAddressToCoinsDatabase::haveCoin(uint160 const &_keyId)
{
	return db.Exists( std::make_pair( 'a', _keyId ) );
}

void
CAddressToCoinsDatabase::clearView()
{
	return db.clear();
}

bool
CAddressToCoinsDatabase::haveCoin(CKeyType const &_keyId)
{
	return db.Exists( std::make_pair( 'c', _keyId ) );
}

CAddressToCoins::CAddressToCoins( size_t _cacheSize)
:CAddressToCoinsDatabase( _cacheSize, false, false )
{

}

bool CAddressToCoins::getCoinsAmount( uint160 const &_keyId, uint64_t & _amount )
{
	_amount = 0;
	CKeyType key( _keyId );

	if ( !haveCoin(_keyId) )
		return false;

	uint64_t potential;
	if ( !CAddressToCoinsDatabase::getCoinsAmount(_keyId, potential) )
		return false;

	while( potential-- )
	{
		uint256 coin;
		if ( haveCoin((CKeyType&)++key) )
		{
			_amount++;
		}
	}
	return true;
}

bool
CAddressToCoins::getCoins( uint160 const &_keyId, std::vector< uint256 > &_coins )
{
	CKeyType key( _keyId );
	uint64_t amount;

	if ( !haveCoin(_keyId) )
		return false;

	if ( !CAddressToCoinsDatabase::getCoinsAmount(_keyId, amount) )
		return false;

	while( amount-- )
	{
		uint256 coin;
		if ( haveCoin((CKeyType&)++key) )
		{
			getCoin( key, coin );
			_coins.push_back( coin );
		}
	}
	return true;
}

typedef std::map< uint256, uint256 > KeyToCoins;

bool CAddressToCoins::eraseCoin( uint160 const &_keyId, uint256 const & _coin )
{
	KeyToCoins keyToCoins;
	if ( !getCoins(_keyId, keyToCoins ) )
		return false;

	KeyToCoins::iterator iterator = keyToCoins.begin();

	while( iterator != keyToCoins.end() )
	{
		if( iterator->second != _coin )
		{
			keyToCoins.erase(iterator++);
		}
		else
		{
			++iterator;
		}
	}

	BOOST_FOREACH( KeyToCoins::value_type & coins, keyToCoins )
	{
		CAddressToCoinsDatabase::eraseCoin( coins.first );
	}
	return true;
}

bool
CAddressToCoins::getCoins( uint160 const &_keyId, std::map< uint256 , uint256 > &_coins )
{
	CKeyType key( _keyId );
	uint64_t amount;

	if ( !haveCoin(_keyId) )
		return false;

	if ( !getCoinsAmount(_keyId, amount) )
		return false;

	while( amount-- )
	{
		uint256 coin;
		if ( haveCoin((CKeyType&)++key) )
		{
			getCoin( key, coin );
			_coins.insert(std::make_pair( key, coin ) );
		}
	}
	return true;
}

bool
CAddressToCoins::setCoins( uint160 const &_keyId, uint256 const & _coin )
{
	uint64_t amount;
	if ( !getCoinsAmount(_keyId, amount) )
		amount = 0;

	if ( !setCoinsAmount(_keyId, ++amount ) )
		return false;

	CKeyType key( _keyId );
	if ( !setCoin((CKeyType &)++key, _coin ) )
	{
		setCoinsAmount(_keyId, --amount );
		return false;
	}
	return true;
}

bool
CAddressToCoins::batchWrite( std::multimap<uint160,uint256> const &mapCoins )
{
	CBatchWrite< uint160, uint64_t, 'a' > amountBatch;
	CBatchWrite< CKeyType, uint256, 'c' > coinsBatch;
	std::multimap<uint160,uint256>::const_iterator iterator = mapCoins.begin(), end;

	while( iterator != mapCoins.end() )
	{
		end = mapCoins.upper_bound( iterator->first );
		uint64_t amount = 0;
		CKeyType key( iterator->first );
		uint160 firstKey = iterator->first;

		getCoinsAmount(firstKey, amount);

		key += amount;

		while( iterator != end )
		{
			amount++;
			coinsBatch.insert( (CKeyType&)++key, iterator->second );

			iterator++;
		}
		amountBatch.insert( firstKey, amount );
	}
	CAddressToCoinsDatabase::batchWrite( amountBatch );
	CAddressToCoinsDatabase::batchWrite( coinsBatch );

	return true;
}

void
CAddressToCoins::clearView()
{
	CAddressToCoinsDatabase::clearView();
}

CAddressToCoinsViewCache * CAddressToCoinsViewCache::ms_instance = NULL;

CAddressToCoinsViewCache*
CAddressToCoinsViewCache::getInstance()
{
	if ( !ms_instance )
	{
		ms_instance = new CAddressToCoinsViewCache();
	};
	return ms_instance;
}

bool CAddressToCoinsViewCache::getCoins( uint160 const &_keyId, std::vector< uint256 > &_coins )
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	std::map<uint160,uint256>::iterator it = fetchCoins(_keyId);

	while(it != cacheCoins.end() && it->first == _keyId)
	{
		_coins.push_back( it->second );
		it++;
	}

	return !_coins.empty();
}

bool CAddressToCoinsViewCache::setCoins( uint160 const &_keyId, uint256 const & _coin )
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	insertCacheCoins.insert( std::make_pair( _keyId, _coin ) );
	return true;
}

bool CAddressToCoinsViewCache::haveCoins(const uint160 &txid)
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	return fetchCoins(txid) != cacheCoins.end();
}

std::map<uint160,uint256>::iterator
CAddressToCoinsViewCache::fetchCoins(const uint160 &_keyId, bool secondPass )
{
	if ( !secondPass )
		boost::lock_guard<boost::mutex> lock( m_cacheLock );

	std::map<uint160,uint256>::iterator it = cacheCoins.lower_bound(_keyId);

	if ( it != cacheCoins.end() && it->first == _keyId )
	{
		unsigned int distance = std::distance( it, cacheCoins.upper_bound(_keyId));

		uint64_t amount;

		m_addressToCoins.getCoinsAmount( _keyId, amount );

		if ( distance == amount )
			return it;

		if ( secondPass )//  ugly  way to indicate error
			throw;
	}
	std::vector< uint256 > tmp;

	if ( !m_addressToCoins.getCoins(_keyId,tmp) )
		return cacheCoins.end();

	BOOST_FOREACH( uint256 & coin, tmp )
	{
		it = cacheCoins.lower_bound( _keyId );

		if ( it == cacheCoins.end() )
			cacheCoins.insert(it, std::make_pair(_keyId, coin));
		else
		{
			bool insert = true;

			std::map<uint160,uint256>::iterator upper = cacheCoins.upper_bound(_keyId);
			while( it!= upper )
			{
				if ( it->second == coin )
				{
					insert =false;
					break;
				}

				it++;
			}

			if ( insert )
				cacheCoins.insert(it, std::make_pair(_keyId, coin));
		}
	}
	return fetchCoins(_keyId, true);

}

bool
CAddressToCoinsViewCache::eraseCoins( uint160 const &_keyId, uint256 const & _coin )
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	std::multimap<uint160,uint256>::iterator iterator = cacheCoins.find( _keyId );

	if ( iterator != cacheCoins.end() && iterator->second == _coin )
		cacheCoins.erase( _keyId );

	m_addressToCoins.eraseCoin( _keyId, _coin );
	return true;
}

bool
CAddressToCoinsViewCache::flush()
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	bool ok = m_addressToCoins.batchWrite(insertCacheCoins);
	if (ok)
		insertCacheCoins.clear();
	return ok;
}

void
CAddressToCoinsViewCache::clearView()
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	insertCacheCoins.clear();
	m_addressToCoins.clearView();
}

CAddressToCoinsViewCache::~CAddressToCoinsViewCache()
{
	ms_instance = 0;
}

}
<commit_msg>fix previous<commit_after>// Copyright (c) 2014 Dims dev-team
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "addressToCoins.h"

#include <boost/foreach.hpp>
//#include <stdint.h>

namespace tracker
{

template <class K, class T, char _prefix >
class CBatchWrite
{
public:
	void insert( K _key, T _object )
	{
		m_batch.Write( std::make_pair(_prefix, _key), _object );
	}
	CLevelDBBatch & getBatch(){ return m_batch; }
private:
	CLevelDBBatch m_batch;
};

CAddressToCoinsDatabase::CAddressToCoinsDatabase(size_t nCacheSize, bool fMemory, bool fWipe)
: db(GetDataDir(common::AppType::Tracker) / "addressTocoins",
	nCacheSize,
	fMemory,
	fWipe)
{
}

bool
CAddressToCoinsDatabase::getCoinsAmount(const uint160 &_keyId, uint64_t & _amount )
{
	return db.Read( std::make_pair('a', _keyId), _amount );
}

bool
CAddressToCoinsDatabase::setCoinsAmount(uint160 const &_keyId, uint64_t const _amount)
{
	return db.Write( std::make_pair('a', _keyId), _amount );
}

bool
CAddressToCoinsDatabase::getCoin(CKeyType const &_keyId, uint256 &coins)
{
	return db.Read( std::make_pair('c', _keyId), coins );
}

bool
CAddressToCoinsDatabase::setCoin(CKeyType const &_keyId, uint256 const &coins)
{
	return db.Write( std::make_pair('c', _keyId), coins );
}

bool
CAddressToCoinsDatabase::eraseCoin( uint256 const &_keyId )
{
	return db.Erase( std::make_pair('c', _keyId) );
}

bool
CAddressToCoinsDatabase::haveCoin(uint160 const &_keyId)
{
	return db.Exists( std::make_pair( 'a', _keyId ) );
}

void
CAddressToCoinsDatabase::clearView()
{
	return db.clear();
}

bool
CAddressToCoinsDatabase::haveCoin(CKeyType const &_keyId)
{
	return db.Exists( std::make_pair( 'c', _keyId ) );
}

CAddressToCoins::CAddressToCoins( size_t _cacheSize)
:CAddressToCoinsDatabase( _cacheSize, false, false )
{

}

bool CAddressToCoins::getCoinsAmount( uint160 const &_keyId, uint64_t & _amount )
{
	_amount = 0;
	CKeyType key( _keyId );

	if ( !haveCoin(_keyId) )
		return false;

	uint64_t potential;
	if ( !CAddressToCoinsDatabase::getCoinsAmount(_keyId, potential) )
		return false;

	while( potential-- )
	{
		uint256 coin;
		if ( haveCoin((CKeyType&)++key) )
		{
			_amount++;
		}
	}
	return true;
}

bool
CAddressToCoins::getCoins( uint160 const &_keyId, std::vector< uint256 > &_coins )
{
	CKeyType key( _keyId );
	uint64_t amount;

	if ( !haveCoin(_keyId) )
		return false;

	if ( !CAddressToCoinsDatabase::getCoinsAmount(_keyId, amount) )
		return false;

	while( amount-- )
	{
		uint256 coin;
		if ( haveCoin((CKeyType&)++key) )
		{
			getCoin( key, coin );
			_coins.push_back( coin );
		}
	}
	return true;
}

typedef std::map< uint256, uint256 > KeyToCoins;

bool CAddressToCoins::eraseCoin( uint160 const &_keyId, uint256 const & _coin )
{
	KeyToCoins keyToCoins;
	if ( !getCoins(_keyId, keyToCoins ) )
		return false;

	KeyToCoins::iterator iterator = keyToCoins.begin();

	while( iterator != keyToCoins.end() )
	{
		if( iterator->second != _coin )
		{
			keyToCoins.erase(iterator++);
		}
		else
		{
			++iterator;
		}
	}

	BOOST_FOREACH( KeyToCoins::value_type & coins, keyToCoins )
	{
		CAddressToCoinsDatabase::eraseCoin( coins.first );
	}
	return true;
}

bool
CAddressToCoins::getCoins( uint160 const &_keyId, std::map< uint256 , uint256 > &_coins )
{
	CKeyType key( _keyId );
	uint64_t amount;

	if ( !haveCoin(_keyId) )
		return false;

	if ( !getCoinsAmount(_keyId, amount) )
		return false;

	while( amount-- )
	{
		uint256 coin;
		if ( haveCoin((CKeyType&)++key) )
		{
			getCoin( key, coin );
			_coins.insert(std::make_pair( key, coin ) );
		}
	}
	return true;
}

bool
CAddressToCoins::setCoins( uint160 const &_keyId, uint256 const & _coin )
{
	uint64_t amount;
	if ( !getCoinsAmount(_keyId, amount) )
		amount = 0;

	if ( !setCoinsAmount(_keyId, ++amount ) )
		return false;

	CKeyType key( _keyId );
	if ( !setCoin((CKeyType &)++key, _coin ) )
	{
		setCoinsAmount(_keyId, --amount );
		return false;
	}
	return true;
}

bool
CAddressToCoins::batchWrite( std::multimap<uint160,uint256> const &mapCoins )
{
	CBatchWrite< uint160, uint64_t, 'a' > amountBatch;
	CBatchWrite< CKeyType, uint256, 'c' > coinsBatch;
	std::multimap<uint160,uint256>::const_iterator iterator = mapCoins.begin(), end;

	while( iterator != mapCoins.end() )
	{
		end = mapCoins.upper_bound( iterator->first );
		uint64_t amount = 0;
		CKeyType key( iterator->first );
		uint160 firstKey = iterator->first;

		getCoinsAmount(firstKey, amount);

		key += amount;

		while( iterator != end )
		{
			amount++;
			coinsBatch.insert( (CKeyType&)++key, iterator->second );

			iterator++;
		}
		amountBatch.insert( firstKey, amount );
	}
	CAddressToCoinsDatabase::batchWrite( amountBatch );
	CAddressToCoinsDatabase::batchWrite( coinsBatch );

	return true;
}

void
CAddressToCoins::clearView()
{
	CAddressToCoinsDatabase::clearView();
}

CAddressToCoinsViewCache * CAddressToCoinsViewCache::ms_instance = NULL;

CAddressToCoinsViewCache*
CAddressToCoinsViewCache::getInstance()
{
	if ( !ms_instance )
	{
		ms_instance = new CAddressToCoinsViewCache();
	};
	return ms_instance;
}

bool CAddressToCoinsViewCache::getCoins( uint160 const &_keyId, std::vector< uint256 > &_coins )
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	std::map<uint160,uint256>::iterator it = fetchCoins(_keyId);

	while(it != cacheCoins.end() && it->first == _keyId)
	{
		_coins.push_back( it->second );
		it++;
	}

	return !_coins.empty();
}

bool CAddressToCoinsViewCache::setCoins( uint160 const &_keyId, uint256 const & _coin )
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	insertCacheCoins.insert( std::make_pair( _keyId, _coin ) );
	return true;
}

bool CAddressToCoinsViewCache::haveCoins(const uint160 &txid)
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	return fetchCoins(txid) != cacheCoins.end();
}

std::map<uint160,uint256>::iterator
CAddressToCoinsViewCache::fetchCoins(const uint160 &_keyId, bool secondPass )
{
	std::map<uint160,uint256>::iterator it = cacheCoins.lower_bound(_keyId);

	if ( it != cacheCoins.end() && it->first == _keyId )
	{
		unsigned int distance = std::distance( it, cacheCoins.upper_bound(_keyId));

		uint64_t amount;

		m_addressToCoins.getCoinsAmount( _keyId, amount );

		if ( distance == amount )
			return it;

		if ( secondPass )//  ugly  way to indicate error
			throw;
	}
	std::vector< uint256 > tmp;

	if ( !m_addressToCoins.getCoins(_keyId,tmp) )
		return cacheCoins.end();

	BOOST_FOREACH( uint256 & coin, tmp )
	{
		it = cacheCoins.lower_bound( _keyId );

		if ( it == cacheCoins.end() )
			cacheCoins.insert(it, std::make_pair(_keyId, coin));
		else
		{
			bool insert = true;

			std::map<uint160,uint256>::iterator upper = cacheCoins.upper_bound(_keyId);
			while( it!= upper )
			{
				if ( it->second == coin )
				{
					insert =false;
					break;
				}

				it++;
			}

			if ( insert )
				cacheCoins.insert(it, std::make_pair(_keyId, coin));
		}
	}
	return fetchCoins(_keyId, true);

}

bool
CAddressToCoinsViewCache::eraseCoins( uint160 const &_keyId, uint256 const & _coin )
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	std::multimap<uint160,uint256>::iterator iterator = cacheCoins.find( _keyId );

	if ( iterator != cacheCoins.end() && iterator->second == _coin )
		cacheCoins.erase( _keyId );

	m_addressToCoins.eraseCoin( _keyId, _coin );
	return true;
}

bool
CAddressToCoinsViewCache::flush()
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	bool ok = m_addressToCoins.batchWrite(insertCacheCoins);
	if (ok)
		insertCacheCoins.clear();
	return ok;
}

void
CAddressToCoinsViewCache::clearView()
{
	boost::lock_guard<boost::mutex> lock( m_cacheLock );

	insertCacheCoins.clear();
	m_addressToCoins.clearView();
}

CAddressToCoinsViewCache::~CAddressToCoinsViewCache()
{
	ms_instance = 0;
}

}
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "AbstractObject.h"

#include <Corrade/Utility/Assert.h>
#include <Corrade/Containers/ArrayView.h>

#include "Magnum/Context.h"
#include "Magnum/Extensions.h"

#include "Implementation/State.h"
#ifndef MAGNUM_TARGET_WEBGL
#include "Implementation/DebugState.h"
#endif

namespace Magnum {

#ifndef MAGNUM_TARGET_WEBGL
#ifndef CORRADE_TARGET_NACL
namespace {
    inline GLenum extTypeFromKhrIdentifier(GLenum khrIdentifier) {
        switch(khrIdentifier) {
            #ifndef MAGNUM_TARGET_GLES
            case GL_BUFFER:
            #else
            case GL_BUFFER_KHR:
            #endif
                return GL_BUFFER_OBJECT_EXT;

            #ifndef MAGNUM_TARGET_GLES
            case GL_SHADER:
            #else
            case GL_SHADER_KHR:
            #endif
                return GL_SHADER_OBJECT_EXT;

            #ifndef MAGNUM_TARGET_GLES
            case GL_PROGRAM:
            #else
            case GL_PROGRAM_KHR:
            #endif
                return GL_PROGRAM_OBJECT_EXT;

            #ifndef MAGNUM_TARGET_GLES
            case GL_VERTEX_ARRAY:
            #else
            case GL_VERTEX_ARRAY_KHR:
            #endif
                return GL_VERTEX_ARRAY_OBJECT_EXT;

            #ifndef MAGNUM_TARGET_GLES
            case GL_QUERY:
            #else
            case GL_QUERY_KHR:
            #endif
                return GL_QUERY_OBJECT_EXT;

            /** @todo Why isn't `GL_PROGRAM_PIPELINE_KHR` in ES's KHR_debug? */
            #ifndef MAGNUM_TARGET_GLES
            case GL_PROGRAM_PIPELINE:
            #else
            case 0x82E4: //GL_PROGRAM_PIPELINE_KHR:
            #endif
                return GL_PROGRAM_PIPELINE_OBJECT_EXT;

            /**
             * @todo Shouldn't ES2's KHR_debug have `GL_TRANSFORM_FEEDBACK_KHR`
             *      instead of `GL_TRANSFORM_FEEDBACK`? (it's a new enum in 2.0)
             *      NaCl extension header doesn't have it at all. Also the
             *      original @es_extension{EXT,debug_label} mentions it only
             *      for ES3 (i.e. no mention of @es_extension{EXT,transform_feedback})
             */
            #ifndef CORRADE_TARGET_NACL
            case GL_TRANSFORM_FEEDBACK:
            #endif
            #ifndef MAGNUM_TARGET_GLES
            case GL_SAMPLER:
            #else
            case GL_SAMPLER_KHR:
            #endif
            case GL_TEXTURE:
            case GL_RENDERBUFFER:
            case GL_FRAMEBUFFER:
                return khrIdentifier;
        }

        CORRADE_ASSERT_UNREACHABLE();
    }
}
#endif

Int AbstractObject::maxLabelLength() {
    if(!Context::current().isExtensionSupported<Extensions::GL::KHR::debug>())
        return 0;

    GLint& value = Context::current().state().debug->maxLabelLength;

    if(value == 0) {
        #ifndef MAGNUM_TARGET_GLES
        glGetIntegerv(GL_MAX_LABEL_LENGTH, &value);
        #else
        glGetIntegerv(GL_MAX_LABEL_LENGTH_KHR, &value);
        #endif
    }

    return value;
}

void AbstractObject::labelImplementationNoOp(GLenum, GLuint, Containers::ArrayView<const char>) {}

void AbstractObject::labelImplementationKhr(const GLenum identifier, const GLuint name, const Containers::ArrayView<const char> label) {
    #ifndef MAGNUM_TARGET_GLES
    glObjectLabel(identifier, name, label.size(), label);
    #elif !defined(CORRADE_TARGET_NACL)
    glObjectLabelKHR(identifier, name, label.size(), label);
    #else
    static_cast<void>(identifier);
    static_cast<void>(name);
    static_cast<void>(label);
    CORRADE_ASSERT_UNREACHABLE();
    #endif
}

void AbstractObject::labelImplementationExt(const GLenum identifier, const GLuint name, const Containers::ArrayView<const char> label) {
    #ifndef CORRADE_TARGET_NACL
    const GLenum type = extTypeFromKhrIdentifier(identifier);
    glLabelObjectEXT(type, name, label.size(), label);
    #else
    static_cast<void>(identifier);
    static_cast<void>(name);
    static_cast<void>(label);
    CORRADE_ASSERT_UNREACHABLE();
    #endif
}

std::string AbstractObject::getLabelImplementationNoOp(GLenum, GLuint) { return  {}; }

std::string AbstractObject::getLabelImplementationKhr(const GLenum identifier, const GLuint name) {
    /* Get label size (w/o null terminator). Specifying 0 as size is not
       allowed, thus we pass the maximum instead. */
    GLsizei size = 0;
    #ifndef MAGNUM_TARGET_GLES
    glGetObjectLabel(identifier, name, maxLabelLength(), &size, nullptr);
    #elif !defined(CORRADE_TARGET_NACL)
    glGetObjectLabelKHR(identifier, name, maxLabelLength(), &size, nullptr);
    #else
    static_cast<void>(identifier);
    static_cast<void>(name);
    CORRADE_ASSERT_UNREACHABLE();
    #endif

    /* Make place also for the null terminator */
    std::string label;
    label.resize(size+1);
    #ifndef MAGNUM_TARGET_GLES
    glGetObjectLabel(identifier, name, size+1, nullptr, &label[0]);
    #elif !defined(CORRADE_TARGET_NACL)
    glGetObjectLabelKHR(identifier, name, size+1, nullptr, &label[0]);
    #else
    CORRADE_ASSERT_UNREACHABLE();
    #endif

    /* Pop null terminator and return the string */
    label.resize(size);
    return label;
}

std::string AbstractObject::getLabelImplementationExt(const GLenum identifier, const GLuint name) {
    GLsizei size = 0;

    /* Get label size (w/o null terminator) */
    #ifndef CORRADE_TARGET_NACL
    const GLenum type = extTypeFromKhrIdentifier(identifier);
    glGetObjectLabelEXT(type, name, 0, &size, nullptr);
    #else
    static_cast<void>(identifier);
    static_cast<void>(name);
    CORRADE_ASSERT_UNREACHABLE();
    #endif

    /* Make place also for the null terminator */
    std::string label;
    label.resize(size+1);
    #ifndef CORRADE_TARGET_NACL
    glGetObjectLabelEXT(identifier, name, size+1, nullptr, &label[0]);
    #else
    CORRADE_ASSERT_UNREACHABLE();
    #endif

    /* Pop null terminator and return the string */
    label.resize(size);
    return label;
}
#endif

}
<commit_msg>Fix object label queries with EXT_debug_label.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014, 2015
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "AbstractObject.h"

#include <Corrade/Utility/Assert.h>
#include <Corrade/Containers/ArrayView.h>

#include "Magnum/Context.h"
#include "Magnum/Extensions.h"

#include "Implementation/State.h"
#ifndef MAGNUM_TARGET_WEBGL
#include "Implementation/DebugState.h"
#endif

namespace Magnum {

#ifndef MAGNUM_TARGET_WEBGL
#ifndef CORRADE_TARGET_NACL
namespace {
    inline GLenum extTypeFromKhrIdentifier(GLenum khrIdentifier) {
        switch(khrIdentifier) {
            #ifndef MAGNUM_TARGET_GLES
            case GL_BUFFER:
            #else
            case GL_BUFFER_KHR:
            #endif
                return GL_BUFFER_OBJECT_EXT;

            #ifndef MAGNUM_TARGET_GLES
            case GL_SHADER:
            #else
            case GL_SHADER_KHR:
            #endif
                return GL_SHADER_OBJECT_EXT;

            #ifndef MAGNUM_TARGET_GLES
            case GL_PROGRAM:
            #else
            case GL_PROGRAM_KHR:
            #endif
                return GL_PROGRAM_OBJECT_EXT;

            #ifndef MAGNUM_TARGET_GLES
            case GL_VERTEX_ARRAY:
            #else
            case GL_VERTEX_ARRAY_KHR:
            #endif
                return GL_VERTEX_ARRAY_OBJECT_EXT;

            #ifndef MAGNUM_TARGET_GLES
            case GL_QUERY:
            #else
            case GL_QUERY_KHR:
            #endif
                return GL_QUERY_OBJECT_EXT;

            /** @todo Why isn't `GL_PROGRAM_PIPELINE_KHR` in ES's KHR_debug? */
            #ifndef MAGNUM_TARGET_GLES
            case GL_PROGRAM_PIPELINE:
            #else
            case 0x82E4: //GL_PROGRAM_PIPELINE_KHR:
            #endif
                return GL_PROGRAM_PIPELINE_OBJECT_EXT;

            /**
             * @todo Shouldn't ES2's KHR_debug have `GL_TRANSFORM_FEEDBACK_KHR`
             *      instead of `GL_TRANSFORM_FEEDBACK`? (it's a new enum in 2.0)
             *      NaCl extension header doesn't have it at all. Also the
             *      original @es_extension{EXT,debug_label} mentions it only
             *      for ES3 (i.e. no mention of @es_extension{EXT,transform_feedback})
             */
            #ifndef CORRADE_TARGET_NACL
            case GL_TRANSFORM_FEEDBACK:
            #endif
            #ifndef MAGNUM_TARGET_GLES
            case GL_SAMPLER:
            #else
            case GL_SAMPLER_KHR:
            #endif
            case GL_TEXTURE:
            case GL_RENDERBUFFER:
            case GL_FRAMEBUFFER:
                return khrIdentifier;
        }

        CORRADE_ASSERT_UNREACHABLE();
    }
}
#endif

Int AbstractObject::maxLabelLength() {
    if(!Context::current().isExtensionSupported<Extensions::GL::KHR::debug>())
        return 0;

    GLint& value = Context::current().state().debug->maxLabelLength;

    if(value == 0) {
        #ifndef MAGNUM_TARGET_GLES
        glGetIntegerv(GL_MAX_LABEL_LENGTH, &value);
        #else
        glGetIntegerv(GL_MAX_LABEL_LENGTH_KHR, &value);
        #endif
    }

    return value;
}

void AbstractObject::labelImplementationNoOp(GLenum, GLuint, Containers::ArrayView<const char>) {}

void AbstractObject::labelImplementationKhr(const GLenum identifier, const GLuint name, const Containers::ArrayView<const char> label) {
    #ifndef MAGNUM_TARGET_GLES
    glObjectLabel(identifier, name, label.size(), label);
    #elif !defined(CORRADE_TARGET_NACL)
    glObjectLabelKHR(identifier, name, label.size(), label);
    #else
    static_cast<void>(identifier);
    static_cast<void>(name);
    static_cast<void>(label);
    CORRADE_ASSERT_UNREACHABLE();
    #endif
}

void AbstractObject::labelImplementationExt(const GLenum identifier, const GLuint name, const Containers::ArrayView<const char> label) {
    #ifndef CORRADE_TARGET_NACL
    const GLenum type = extTypeFromKhrIdentifier(identifier);
    glLabelObjectEXT(type, name, label.size(), label);
    #else
    static_cast<void>(identifier);
    static_cast<void>(name);
    static_cast<void>(label);
    CORRADE_ASSERT_UNREACHABLE();
    #endif
}

std::string AbstractObject::getLabelImplementationNoOp(GLenum, GLuint) { return  {}; }

std::string AbstractObject::getLabelImplementationKhr(const GLenum identifier, const GLuint name) {
    /* Get label size (w/o null terminator). Specifying 0 as size is not
       allowed, thus we pass the maximum instead. */
    GLsizei size = 0;
    #ifndef MAGNUM_TARGET_GLES
    glGetObjectLabel(identifier, name, maxLabelLength(), &size, nullptr);
    #elif !defined(CORRADE_TARGET_NACL)
    glGetObjectLabelKHR(identifier, name, maxLabelLength(), &size, nullptr);
    #else
    static_cast<void>(identifier);
    static_cast<void>(name);
    CORRADE_ASSERT_UNREACHABLE();
    #endif

    /* Make place also for the null terminator */
    std::string label;
    label.resize(size+1);
    #ifndef MAGNUM_TARGET_GLES
    glGetObjectLabel(identifier, name, size+1, nullptr, &label[0]);
    #elif !defined(CORRADE_TARGET_NACL)
    glGetObjectLabelKHR(identifier, name, size+1, nullptr, &label[0]);
    #else
    CORRADE_ASSERT_UNREACHABLE();
    #endif

    /* Pop null terminator and return the string */
    label.resize(size);
    return label;
}

std::string AbstractObject::getLabelImplementationExt(const GLenum identifier, const GLuint name) {
    GLsizei size = 0;

    /* Get label size (w/o null terminator) */
    #ifndef CORRADE_TARGET_NACL
    const GLenum type = extTypeFromKhrIdentifier(identifier);
    glGetObjectLabelEXT(type, name, 0, &size, nullptr);
    #else
    static_cast<void>(identifier);
    static_cast<void>(name);
    CORRADE_ASSERT_UNREACHABLE();
    #endif

    /* Make place also for the null terminator */
    std::string label;
    label.resize(size+1);
    #ifndef CORRADE_TARGET_NACL
    glGetObjectLabelEXT(type, name, size+1, nullptr, &label[0]);
    #else
    CORRADE_ASSERT_UNREACHABLE();
    #endif

    /* Pop null terminator and return the string */
    label.resize(size);
    return label;
}
#endif

}
<|endoftext|>


<commit_before>/*
  Copyright 2013 SINTEF ICT, Applied Mathematics.
*/

extern int yylex();
extern int yyparse();

#include "SymbolTable.hpp"
#include "CheckASTVisitor.hpp"
#include "PrintASTVisitor.hpp"
#include "PrintEquelleASTVisitor.hpp"
#include "PrintCPUBackendASTVisitor.hpp"
#include "PrintMRSTBackendASTVisitor.hpp"
#include "PrintCUDABackendASTVisitor.hpp"
#include "PrintMPIBackendASTVisitor.hpp"
#include "PrintIOVisitor.hpp"
#include "ASTNodes.hpp"
#include "CommandLineOptions.hpp"

#include <iostream>

extern int yylex();
extern int yyparse();
extern FILE * yyin;

/**
 * Trivial class to properly close yyin
 */
class YYInOwner {
public:
	YYInOwner(const std::string filename_) {
		yyin = fopen(filename_.c_str(),"r");
                if (!yyin) {
                    throw std::runtime_error("Input file not found.");
                }
	}
	~YYInOwner() {
	    fclose(yyin);
	    yyin = NULL;
	}
};

int main(int argc, char** argv)
{
	CommandLineOptions options;
	boost::program_options::variables_map cli_vars;
	boost::shared_ptr<YYInOwner> yyin_owner;

	//Parse commandline
	try {
		cli_vars = options.parse(argc, argv);

		if (cli_vars.count("help")) {
			std::cout << "Usage: ./eq <options>" << std::endl;
			std::cout << "The following options are supported:" << std::endl;
			options.printOptions();
			return -1;
		}
		if (cli_vars.count("verbose")) {
			options.printVars(cli_vars);
		}
	}
	catch (const std::exception& e) {
		std::cerr << "Usage: ./eq <options>" << std::endl;
		std::cerr << "The following options are supported:" << std::endl;
		options.printOptions();
		std::cerr << std::endl;
        std::cerr << "Error parsing options: ";
        std::cerr << e.what() << std::endl;
		return -1;
	}

	//Get input file
	if (cli_vars.count("input")) {
		std::string infile = cli_vars["input"].as<std::string>();
		if (infile != "-") { //"-" signifies use stdin
			yyin_owner.reset(new YYInOwner(infile));
		}
	}

	//Parse equelle program
    yyparse();

    // Check AST (and build symbol table)
    const bool ignore_dimensions = cli_vars.count("nondimensional");
    CheckASTVisitor check(ignore_dimensions);
    SymbolTable::program()->accept(check);

    // Dump the SymbolTable
    if (cli_vars["dump"].as<std::string>() == "symboltable") {
        SymbolTable::dump();
    }
    //Write output
    else {
        std::string backend = cli_vars["backend"].as<std::string>();
        if (backend == "ast") {
            PrintASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if (backend == "equelle_ast") {
            PrintEquelleASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if (backend == "cpu") {
            // Check if we use the Cartesian dialect
            const bool use_cartesian = cli_vars.count("cartesian");
            PrintCPUBackendASTVisitor v(use_cartesian);
            SymbolTable::program()->accept(v);
        }
        else if (backend == "cuda") {
            PrintCUDABackendASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if (backend == "mrst") {
            PrintMRSTBackendASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if(backend == "MPI") {
            PrintMPIBackendASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if(backend == "io") {
            PrintIOVisitor v;
            SymbolTable::program()->accept(v);
        }
        else {
            std::cerr << "Unknown back-end choice: " << backend << '\n';
        }
    }

    //This assumes that the printing went well.
    if (check.isValid())
    {
    	return 0;
    }
    else
    {
    	return -1;
    }
}
<commit_msg>Delete extra declarations.<commit_after>/*
  Copyright 2013 SINTEF ICT, Applied Mathematics.
*/

#include "SymbolTable.hpp"
#include "CheckASTVisitor.hpp"
#include "PrintASTVisitor.hpp"
#include "PrintEquelleASTVisitor.hpp"
#include "PrintCPUBackendASTVisitor.hpp"
#include "PrintMRSTBackendASTVisitor.hpp"
#include "PrintCUDABackendASTVisitor.hpp"
#include "PrintMPIBackendASTVisitor.hpp"
#include "PrintIOVisitor.hpp"
#include "ASTNodes.hpp"
#include "CommandLineOptions.hpp"

#include <iostream>

extern int yylex();
extern int yyparse();
extern FILE * yyin;

/**
 * Trivial class to properly close yyin
 */
class YYInOwner {
public:
	YYInOwner(const std::string filename_) {
		yyin = fopen(filename_.c_str(),"r");
                if (!yyin) {
                    throw std::runtime_error("Input file not found.");
                }
	}
	~YYInOwner() {
	    fclose(yyin);
	    yyin = NULL;
	}
};

int main(int argc, char** argv)
{
	CommandLineOptions options;
	boost::program_options::variables_map cli_vars;
	boost::shared_ptr<YYInOwner> yyin_owner;

	//Parse commandline
	try {
		cli_vars = options.parse(argc, argv);

		if (cli_vars.count("help")) {
			std::cout << "Usage: ./eq <options>" << std::endl;
			std::cout << "The following options are supported:" << std::endl;
			options.printOptions();
			return -1;
		}
		if (cli_vars.count("verbose")) {
			options.printVars(cli_vars);
		}
	}
	catch (const std::exception& e) {
		std::cerr << "Usage: ./eq <options>" << std::endl;
		std::cerr << "The following options are supported:" << std::endl;
		options.printOptions();
		std::cerr << std::endl;
        std::cerr << "Error parsing options: ";
        std::cerr << e.what() << std::endl;
		return -1;
	}

	//Get input file
	if (cli_vars.count("input")) {
		std::string infile = cli_vars["input"].as<std::string>();
		if (infile != "-") { //"-" signifies use stdin
			yyin_owner.reset(new YYInOwner(infile));
		}
	}

	//Parse equelle program
    yyparse();

    // Check AST (and build symbol table)
    const bool ignore_dimensions = cli_vars.count("nondimensional");
    CheckASTVisitor check(ignore_dimensions);
    SymbolTable::program()->accept(check);

    // Dump the SymbolTable
    if (cli_vars["dump"].as<std::string>() == "symboltable") {
        SymbolTable::dump();
    }
    //Write output
    else {
        std::string backend = cli_vars["backend"].as<std::string>();
        if (backend == "ast") {
            PrintASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if (backend == "equelle_ast") {
            PrintEquelleASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if (backend == "cpu") {
            // Check if we use the Cartesian dialect
            const bool use_cartesian = cli_vars.count("cartesian");
            PrintCPUBackendASTVisitor v(use_cartesian);
            SymbolTable::program()->accept(v);
        }
        else if (backend == "cuda") {
            PrintCUDABackendASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if (backend == "mrst") {
            PrintMRSTBackendASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if(backend == "MPI") {
            PrintMPIBackendASTVisitor v;
            SymbolTable::program()->accept(v);
        }
        else if(backend == "io") {
            PrintIOVisitor v;
            SymbolTable::program()->accept(v);
        }
        else {
            std::cerr << "Unknown back-end choice: " << backend << '\n';
        }
    }

    //This assumes that the printing went well.
    if (check.isValid())
    {
    	return 0;
    }
    else
    {
    	return -1;
    }
}
<|endoftext|>