<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.	All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *	  notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *	  if any, must include the following acknowledgment:
 *		 "This product includes software developed by the
 *		  Apache Software Foundation (http://www.apache.org/)."
 *	  Alternately, this acknowledgment may appear in the software itself,
 *	  if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *	  not be used to endorse or promote products derived from this
 *	  software without prior written permission. For written
 *	  permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *	  nor may "Apache" appear in their name, without prior written
 *	  permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "XalanSourceTreeContentHandler.hpp"

#include <XalanDOM/XalanDOMException.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>

#include "XalanSourceTreeDocument.hpp"
#include "XalanSourceTreeElement.hpp"
#include "XalanSourceTreeHelper.hpp"

XalanSourceTreeContentHandler::XalanSourceTreeContentHandler(
			XalanSourceTreeDocument*	theDocument,
			bool						fAccumulateText) :
	ContentHandler(),
	DTDHandler(),
	LexicalHandler(),
	m_document(theDocument),
	m_currentElement(0),
	m_elementStack(),
	m_lastChild(0),
	m_lastChildStack(),
	m_accumulateText(fAccumulateText),
	m_textBuffer(),
	m_inDTD(false)
{
}

XalanSourceTreeContentHandler::~XalanSourceTreeContentHandler()
{
}

void
XalanSourceTreeContentHandler::characters(
			const	XMLCh* const	chars,
			const unsigned int		length)
{
	assert(m_inDTD == false);

	if (m_currentElement == 0)
	{
		if (isXMLWhitespace(chars) == false)
		{
			throw XalanDOMException(XalanDOMException::HIERARCHY_REQUEST_ERR);
		}
	}
	else if (m_accumulateText == true)
	{
		append(m_textBuffer, chars, length);
	}
	else
	{
		doCharacters(chars, length);
	}
}

void
XalanSourceTreeContentHandler::endDocument()
{
	assert(m_inDTD == false);

	// Pop off the dummy value that we pushed in
	// startDocument()...
	m_elementStack.pop_back();

	assert(m_document->getDocumentElement() != 0);

	assert(m_elementStack.empty() == true);
	assert(m_lastChildStack.empty() == true);

	assert(isEmpty(m_textBuffer) == true);
}

void
XalanSourceTreeContentHandler::endElement(
			const XMLCh* const	/* uri */,
			const XMLCh* const	/* localname */,
			const XMLCh* const	/* qname */)
{
	assert(m_inDTD == false);

	// Process any text that we may have accumulated...
	processAccumulatedText();

	assert(m_elementStack.empty() == false);

	// Pop the element of the stack...
	m_elementStack.pop_back();

	assert(m_elementStack.empty() == false);

	// Get the element from the back of the
	// stack.
	m_currentElement = m_elementStack.back();

	assert(m_lastChildStack.empty() == false);

	m_lastChild = m_lastChildStack.back();

	// Pop the last child stack
	m_lastChildStack.pop_back();
}

// A helper function to manage appending the new child.
template <class ParentNodeType, class ChildNodeType>
inline void
doAppendChildNode(
			ParentNodeType*		theParent,
			XalanNode*&			theLastChild,
			ChildNodeType		theNewChild)
{
	assert(theParent != 0);
	assert(theNewChild != 0);

	if (theLastChild == 0)
	{
		theParent->appendChildNode(theNewChild);
	}
	else
	{
		XalanSourceTreeHelper::appendSibling(theLastChild, theNewChild);
	}

	theLastChild = theNewChild;
}

// A helper function to manage appending the new child.
template <class ChildNodeType>
inline void
doAppendChildNode(
			XalanSourceTreeDocument*	theDocument,
			XalanSourceTreeElement*		theCurrentElement,
			XalanNode*&					theLastChild,
			ChildNodeType				theNewChild)
{
	assert(theDocument != 0);
	assert(theNewChild != 0);

	if (theCurrentElement == 0)
	{
		// If there is no current element. it means we haven't
		// created the document element yet, so always append
		// to the document, rather than the last child.
		theDocument->appendChildNode(theNewChild);
	}
	else
	{
		doAppendChildNode(theCurrentElement, theLastChild, theNewChild);
	}
}

void
XalanSourceTreeContentHandler::ignorableWhitespace(
			const XMLCh* const	chars,
			const unsigned int	length)
{
	assert(m_inDTD == false);

	// Ignore any whitespace reported before the document element has been parsed.
	if (m_elementStack.empty() == false)
	{
		assert(m_currentElement != 0);

		processAccumulatedText();

		XalanSourceTreeText*	theNewTextNode =
			m_document->createTextIWSNode(chars, length, m_currentElement);

		doAppendChildNode(m_currentElement, m_lastChild, theNewTextNode);
	}
}

void
XalanSourceTreeContentHandler::processingInstruction(
		const XMLCh* const	target,
		const XMLCh* const	data)
{
	assert(m_inDTD == false);

	processAccumulatedText();

	XalanSourceTreeProcessingInstruction* const		theNewPI =
		m_document->createProcessingInstructionNode(target, data, m_currentElement);

	doAppendChildNode(
			m_document,
			m_currentElement,
			m_lastChild,
			theNewPI);
}

void
XalanSourceTreeContentHandler::setDocumentLocator(const Locator* const	/* locator */)
{
}

void
XalanSourceTreeContentHandler::startDocument()
{
	assert(m_inDTD == false);

	m_currentElement = 0;

	m_elementStack.clear();

	m_elementStack.reserve(eDefaultStackSize);

	m_lastChild = 0;

	m_lastChildStack.clear();

	m_lastChildStack.reserve(eDefaultStackSize);

	if (m_accumulateText == true)
	{
		clear(m_textBuffer);

		reserve(m_textBuffer, eDefaultTextBufferSize);
	}

	// Push a dummy value for the current element, so we
	// don't have to check for an empty stack in endElement().
	m_elementStack.push_back(ElementStackType::value_type(0));
}

void
XalanSourceTreeContentHandler::startElement(
			const XMLCh* const	uri,
			const XMLCh* const	localname,
			const XMLCh* const	qname,
			const Attributes& 	attrs)
{
	assert(m_inDTD == false);

	processAccumulatedText();

	XalanSourceTreeElement* const	theNewElement =
		createElement(uri, localname, qname, attrs, m_currentElement);

	doAppendChildNode(
			m_document,
			m_currentElement,
			m_lastChild,
			theNewElement);

	m_elementStack.push_back(theNewElement);

	m_lastChildStack.push_back(m_lastChild);

	m_currentElement = theNewElement;

	m_lastChild = 0;
}

void
XalanSourceTreeContentHandler::startPrefixMapping(
		const XMLCh* const	/* prefix */,
		const XMLCh* const	/* uri */)
{
	assert(m_inDTD == false);
}

void
XalanSourceTreeContentHandler::endPrefixMapping(const XMLCh* const	/* prefix */)
{
	assert(m_inDTD == false);
}

void
XalanSourceTreeContentHandler::skippedEntity(const XMLCh* const		/* name */)
{
}

void
XalanSourceTreeContentHandler::notationDecl(
			const XMLCh* const    name,
			const XMLCh* const    publicId,
			const XMLCh* const    systemId)
{
}

void
XalanSourceTreeContentHandler::unparsedEntityDecl(
			const XMLCh* const    name,
			const XMLCh* const    publicId,
			const XMLCh* const    systemId,
			const XMLCh* const    notationName)
{
	assert(m_document != 0);

	m_document->unparsedEntityDeclaration(name, publicId, systemId, notationName);
}

void
XalanSourceTreeContentHandler::resetDocType()
{
}

void
XalanSourceTreeContentHandler::comment(
			const XMLCh* const	chars,
			const unsigned int	length)
{
	assert(m_document != 0);

	if (m_inDTD == false)
	{
		processAccumulatedText();

		XalanSourceTreeComment* const	theNewComment =
			m_document->createCommentNode(chars, length, m_currentElement);

		doAppendChildNode(
				m_document,
				m_currentElement,
				m_lastChild,
				theNewComment);
	}
}

void
XalanSourceTreeContentHandler::endCDATA()
{
	assert(m_inDTD == false);
}

void
XalanSourceTreeContentHandler::endDTD()
{
	m_inDTD = false;

	assert(m_document != 0);
}

void
XalanSourceTreeContentHandler::endEntity(const XMLCh* const		name)
{
	assert(m_document != 0);
}

void
XalanSourceTreeContentHandler::startCDATA()
{
	assert(m_inDTD == false);
}

void
XalanSourceTreeContentHandler::startDTD(
			const XMLCh* const	name,
			const XMLCh* const	publicId,
			const XMLCh* const	systemId)
{
	assert(m_inDTD == false);
	assert(m_document != 0);

	m_inDTD = true;
}

void
XalanSourceTreeContentHandler::startEntity(const XMLCh* const	name)
{
	assert(m_document != 0);
}

void
XalanSourceTreeContentHandler::setDocument(XalanSourceTreeDocument*	theDocument)
{
	m_document = theDocument;
}

XalanSourceTreeElement*
XalanSourceTreeContentHandler::createElement(
			const XMLCh* const			uri,
			const XMLCh* const			localname,
			const XMLCh* const			qname,
			const Attributes& 			attrs,
			XalanSourceTreeElement*		theOwnerElement)
{
	assert(m_inDTD == false);

	// If we're creating the document element, add the special xml namespace attribute...
	const bool	fAddXMLNamespaceAttribute = theOwnerElement == 0 ? true : false;

	if (length(uri) != 0)
	{
		return m_document->createElementNode(uri, localname, qname, attrs, theOwnerElement, 0, 0, fAddXMLNamespaceAttribute);
	}
	else
	{
		return m_document->createElementNode(qname, attrs, theOwnerElement, 0, 0, fAddXMLNamespaceAttribute);
	}
}

void
XalanSourceTreeContentHandler::processAccumulatedText()
{
	assert(m_inDTD == false);

	if (isEmpty(m_textBuffer) == false)
	{
		assert(unsigned(length(m_textBuffer)) == length(m_textBuffer));

		doCharacters(c_wstr(m_textBuffer), length(m_textBuffer));

		clear(m_textBuffer);
	}
}

void
XalanSourceTreeContentHandler::doCharacters(
			const XMLCh*	chars,
			unsigned int	length)
{
	assert(m_inDTD == false);

	assert(m_currentElement != 0);

	XalanSourceTreeText*	theNewTextNode =
				m_document->createTextNode(chars, length, m_currentElement);

	doAppendChildNode(m_currentElement, m_lastChild, theNewTextNode);
}
<commit_msg>Added assert.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 1999-2000 The Apache Software Foundation.	All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *	  notice, this list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. The end-user documentation included with the redistribution,
 *	  if any, must include the following acknowledgment:
 *		 "This product includes software developed by the
 *		  Apache Software Foundation (http://www.apache.org/)."
 *	  Alternately, this acknowledgment may appear in the software itself,
 *	  if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *	  not be used to endorse or promote products derived from this
 *	  software without prior written permission. For written
 *	  permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *	  nor may "Apache" appear in their name, without prior written
 *	  permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR
 * ITS 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.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

#include "XalanSourceTreeContentHandler.hpp"

#include <XalanDOM/XalanDOMException.hpp>

#include <PlatformSupport/DOMStringHelper.hpp>

#include "XalanSourceTreeDocument.hpp"
#include "XalanSourceTreeElement.hpp"
#include "XalanSourceTreeHelper.hpp"

XalanSourceTreeContentHandler::XalanSourceTreeContentHandler(
			XalanSourceTreeDocument*	theDocument,
			bool						fAccumulateText) :
	ContentHandler(),
	DTDHandler(),
	LexicalHandler(),
	m_document(theDocument),
	m_currentElement(0),
	m_elementStack(),
	m_lastChild(0),
	m_lastChildStack(),
	m_accumulateText(fAccumulateText),
	m_textBuffer(),
	m_inDTD(false)
{
}

XalanSourceTreeContentHandler::~XalanSourceTreeContentHandler()
{
}

void
XalanSourceTreeContentHandler::characters(
			const	XMLCh* const	chars,
			const unsigned int		length)
{
	assert(m_inDTD == false);

	if (m_currentElement == 0)
	{
		if (isXMLWhitespace(chars) == false)
		{
			throw XalanDOMException(XalanDOMException::HIERARCHY_REQUEST_ERR);
		}
	}
	else if (m_accumulateText == true)
	{
		append(m_textBuffer, chars, length);
	}
	else
	{
		doCharacters(chars, length);
	}
}

void
XalanSourceTreeContentHandler::endDocument()
{
	assert(m_inDTD == false);

	// Pop off the dummy value that we pushed in
	// startDocument()...
	m_elementStack.pop_back();

	assert(m_document->getDocumentElement() != 0);

	assert(m_elementStack.empty() == true);
	assert(m_lastChildStack.empty() == true);

	assert(isEmpty(m_textBuffer) == true);
}

void
XalanSourceTreeContentHandler::endElement(
			const XMLCh* const	/* uri */,
			const XMLCh* const	/* localname */,
			const XMLCh* const	/* qname */)
{
	assert(m_inDTD == false);

	// Process any text that we may have accumulated...
	processAccumulatedText();

	assert(m_elementStack.empty() == false);

	// Pop the element of the stack...
	m_elementStack.pop_back();

	assert(m_elementStack.empty() == false);

	// Get the element from the back of the
	// stack.
	m_currentElement = m_elementStack.back();

	assert(m_lastChildStack.empty() == false);

	m_lastChild = m_lastChildStack.back();

	// Pop the last child stack
	m_lastChildStack.pop_back();
}

// A helper function to manage appending the new child.
template <class ParentNodeType, class ChildNodeType>
inline void
doAppendChildNode(
			ParentNodeType*		theParent,
			XalanNode*&			theLastChild,
			ChildNodeType		theNewChild)
{
	assert(theParent != 0);
	assert(theNewChild != 0);

	if (theLastChild == 0)
	{
		theParent->appendChildNode(theNewChild);
	}
	else
	{
		XalanSourceTreeHelper::appendSibling(theLastChild, theNewChild);
	}

	theLastChild = theNewChild;
}

// A helper function to manage appending the new child.
template <class ChildNodeType>
inline void
doAppendChildNode(
			XalanSourceTreeDocument*	theDocument,
			XalanSourceTreeElement*		theCurrentElement,
			XalanNode*&					theLastChild,
			ChildNodeType				theNewChild)
{
	assert(theDocument != 0);
	assert(theNewChild != 0);

	if (theCurrentElement == 0)
	{
		// If there is no current element. it means we haven't
		// created the document element yet, so always append
		// to the document, rather than the last child.
		theDocument->appendChildNode(theNewChild);
	}
	else
	{
		doAppendChildNode(theCurrentElement, theLastChild, theNewChild);
	}
}

void
XalanSourceTreeContentHandler::ignorableWhitespace(
			const XMLCh* const	chars,
			const unsigned int	length)
{
	assert(m_inDTD == false);

	// Ignore any whitespace reported before the document element has been parsed.
	if (m_elementStack.empty() == false)
	{
		assert(m_currentElement != 0);

		processAccumulatedText();

		XalanSourceTreeText*	theNewTextNode =
			m_document->createTextIWSNode(chars, length, m_currentElement);

		doAppendChildNode(m_currentElement, m_lastChild, theNewTextNode);
	}
}

void
XalanSourceTreeContentHandler::processingInstruction(
		const XMLCh* const	target,
		const XMLCh* const	data)
{
	assert(m_inDTD == false);

	processAccumulatedText();

	XalanSourceTreeProcessingInstruction* const		theNewPI =
		m_document->createProcessingInstructionNode(target, data, m_currentElement);

	doAppendChildNode(
			m_document,
			m_currentElement,
			m_lastChild,
			theNewPI);
}

void
XalanSourceTreeContentHandler::setDocumentLocator(const Locator* const	/* locator */)
{
}

void
XalanSourceTreeContentHandler::startDocument()
{
	assert(m_inDTD == false);

	m_currentElement = 0;

	m_elementStack.clear();

	m_elementStack.reserve(eDefaultStackSize);

	m_lastChild = 0;

	m_lastChildStack.clear();

	m_lastChildStack.reserve(eDefaultStackSize);

	if (m_accumulateText == true)
	{
		clear(m_textBuffer);

		reserve(m_textBuffer, eDefaultTextBufferSize);
	}

	// Push a dummy value for the current element, so we
	// don't have to check for an empty stack in endElement().
	m_elementStack.push_back(ElementStackType::value_type(0));
}

void
XalanSourceTreeContentHandler::startElement(
			const XMLCh* const	uri,
			const XMLCh* const	localname,
			const XMLCh* const	qname,
			const Attributes& 	attrs)
{
	assert(m_inDTD == false);

	processAccumulatedText();

	XalanSourceTreeElement* const	theNewElement =
		createElement(uri, localname, qname, attrs, m_currentElement);

	doAppendChildNode(
			m_document,
			m_currentElement,
			m_lastChild,
			theNewElement);

	m_elementStack.push_back(theNewElement);

	m_lastChildStack.push_back(m_lastChild);

	m_currentElement = theNewElement;

	m_lastChild = 0;
}

void
XalanSourceTreeContentHandler::startPrefixMapping(
		const XMLCh* const	/* prefix */,
		const XMLCh* const	/* uri */)
{
	assert(m_inDTD == false);
}

void
XalanSourceTreeContentHandler::endPrefixMapping(const XMLCh* const	/* prefix */)
{
	assert(m_inDTD == false);
}

void
XalanSourceTreeContentHandler::skippedEntity(const XMLCh* const		/* name */)
{
}

void
XalanSourceTreeContentHandler::notationDecl(
			const XMLCh* const    name,
			const XMLCh* const    publicId,
			const XMLCh* const    systemId)
{
}

void
XalanSourceTreeContentHandler::unparsedEntityDecl(
			const XMLCh* const    name,
			const XMLCh* const    publicId,
			const XMLCh* const    systemId,
			const XMLCh* const    notationName)
{
	assert(m_document != 0);

	m_document->unparsedEntityDeclaration(name, publicId, systemId, notationName);
}

void
XalanSourceTreeContentHandler::resetDocType()
{
}

void
XalanSourceTreeContentHandler::comment(
			const XMLCh* const	chars,
			const unsigned int	length)
{
	assert(m_document != 0);

	if (m_inDTD == false)
	{
		processAccumulatedText();

		XalanSourceTreeComment* const	theNewComment =
			m_document->createCommentNode(chars, length, m_currentElement);

		doAppendChildNode(
				m_document,
				m_currentElement,
				m_lastChild,
				theNewComment);
	}
}

void
XalanSourceTreeContentHandler::endCDATA()
{
	assert(m_inDTD == false);
}

void
XalanSourceTreeContentHandler::endDTD()
{
	assert(m_document != 0);
	assert(m_inDTD == true);

	m_inDTD = false;
}

void
XalanSourceTreeContentHandler::endEntity(const XMLCh* const		name)
{
	assert(m_document != 0);
}

void
XalanSourceTreeContentHandler::startCDATA()
{
	assert(m_inDTD == false);
}

void
XalanSourceTreeContentHandler::startDTD(
			const XMLCh* const	name,
			const XMLCh* const	publicId,
			const XMLCh* const	systemId)
{
	assert(m_inDTD == false);
	assert(m_document != 0);

	m_inDTD = true;
}

void
XalanSourceTreeContentHandler::startEntity(const XMLCh* const	name)
{
	assert(m_document != 0);
}

void
XalanSourceTreeContentHandler::setDocument(XalanSourceTreeDocument*	theDocument)
{
	m_document = theDocument;
}

XalanSourceTreeElement*
XalanSourceTreeContentHandler::createElement(
			const XMLCh* const			uri,
			const XMLCh* const			localname,
			const XMLCh* const			qname,
			const Attributes& 			attrs,
			XalanSourceTreeElement*		theOwnerElement)
{
	assert(m_inDTD == false);

	// If we're creating the document element, add the special xml namespace attribute...
	const bool	fAddXMLNamespaceAttribute = theOwnerElement == 0 ? true : false;

	if (length(uri) != 0)
	{
		return m_document->createElementNode(uri, localname, qname, attrs, theOwnerElement, 0, 0, fAddXMLNamespaceAttribute);
	}
	else
	{
		return m_document->createElementNode(qname, attrs, theOwnerElement, 0, 0, fAddXMLNamespaceAttribute);
	}
}

void
XalanSourceTreeContentHandler::processAccumulatedText()
{
	assert(m_inDTD == false);

	if (isEmpty(m_textBuffer) == false)
	{
		assert(unsigned(length(m_textBuffer)) == length(m_textBuffer));

		doCharacters(c_wstr(m_textBuffer), length(m_textBuffer));

		clear(m_textBuffer);
	}
}

void
XalanSourceTreeContentHandler::doCharacters(
			const XMLCh*	chars,
			unsigned int	length)
{
	assert(m_inDTD == false);

	assert(m_currentElement != 0);

	XalanSourceTreeText*	theNewTextNode =
				m_document->createTextNode(chars, length, m_currentElement);

	doAppendChildNode(m_currentElement, m_lastChild, theNewTextNode);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <QDebug>
#include "multimedia/qlocalmediaplaylistprovider.h"
#include "multimedia/qmediaplaylistnavigator.h"

class tst_QMediaPlaylistNavigator : public QObject
{
    Q_OBJECT
public slots:
    void init();
    void cleanup();

private slots:
    void construction();
    void setPlaylist();
    void linearPlayback();
    void loopPlayback();
    void currentItemOnce();
    void currentItemInLoop();
    void randomPlayback();
};

void tst_QMediaPlaylistNavigator::init()
{
}

void tst_QMediaPlaylistNavigator::cleanup()
{
}

void tst_QMediaPlaylistNavigator::construction()
{
    QLocalMediaPlaylistProvider playlist;
    QCOMPARE(playlist.size(), 0);

    QMediaPlaylistNavigator navigator(&playlist);
    QVERIFY(navigator.currentItem().isNull());
    QCOMPARE(navigator.currentPosition(), -1);
}

void tst_QMediaPlaylistNavigator::setPlaylist()
{
    QMediaPlaylistNavigator navigator(0);
    QVERIFY(navigator.playlist() != 0);
    QCOMPARE(navigator.playlist()->size(), 0);
    QVERIFY(navigator.playlist()->isReadOnly() );

    QLocalMediaPlaylistProvider playlist;
    QCOMPARE(playlist.size(), 0);

    navigator.setPlaylist(&playlist);
    QCOMPARE(navigator.playlist(), &playlist);
    QCOMPARE(navigator.playlist()->size(), 0);
    QVERIFY(!navigator.playlist()->isReadOnly() );
}

void tst_QMediaPlaylistNavigator::linearPlayback()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::Linear);
    QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range ");
    navigator.jump(0);//it's ok to have warning here
    QVERIFY(navigator.currentItem().isNull());
    QCOMPARE(navigator.currentPosition(), -1);

    QMediaContent content1(QUrl(QLatin1String("file:///1")));
    playlist.appendItem(content1);
    navigator.jump(0);
    QVERIFY(!navigator.currentItem().isNull());

    QCOMPARE(navigator.currentPosition(), 0);
    QCOMPARE(navigator.currentItem(), content1);
    QCOMPARE(navigator.nextItem(), QMediaContent());
    QCOMPARE(navigator.nextItem(2), QMediaContent());
    QCOMPARE(navigator.previousItem(), QMediaContent());
    QCOMPARE(navigator.previousItem(2), QMediaContent());

    QMediaContent content2(QUrl(QLatin1String("file:///2")));
    playlist.appendItem(content2);
    QCOMPARE(navigator.currentPosition(), 0);
    QCOMPARE(navigator.currentItem(), content1);
    QCOMPARE(navigator.nextItem(), content2);
    QCOMPARE(navigator.nextItem(2), QMediaContent());
    QCOMPARE(navigator.previousItem(), QMediaContent());
    QCOMPARE(navigator.previousItem(2), QMediaContent());

    navigator.jump(1);
    QCOMPARE(navigator.currentPosition(), 1);
    QCOMPARE(navigator.currentItem(), content2);
    QCOMPARE(navigator.nextItem(), QMediaContent());
    QCOMPARE(navigator.nextItem(2), QMediaContent());
    QCOMPARE(navigator.previousItem(), content1);
    QCOMPARE(navigator.previousItem(2), QMediaContent());

    navigator.jump(0);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();//jump to the first item
    QCOMPARE(navigator.currentPosition(), 0);

    navigator.previous();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.previous();//jump to the last item
    QCOMPARE(navigator.currentPosition(), 1);
}

void tst_QMediaPlaylistNavigator::loopPlayback()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::Loop);
    QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range ");
    navigator.jump(0);
    QVERIFY(navigator.currentItem().isNull());
    QCOMPARE(navigator.currentPosition(), -1);

    QMediaContent content1(QUrl(QLatin1String("file:///1")));
    playlist.appendItem(content1);
    navigator.jump(0);
    QVERIFY(!navigator.currentItem().isNull());

    QCOMPARE(navigator.currentPosition(), 0);
    QCOMPARE(navigator.currentItem(), content1);
    QCOMPARE(navigator.nextItem(), content1);
    QCOMPARE(navigator.nextItem(2), content1);
    QCOMPARE(navigator.previousItem(), content1);
    QCOMPARE(navigator.previousItem(2), content1);

    QMediaContent content2(QUrl(QLatin1String("file:///2")));
    playlist.appendItem(content2);
    QCOMPARE(navigator.currentPosition(), 0);
    QCOMPARE(navigator.currentItem(), content1);
    QCOMPARE(navigator.nextItem(), content2);
    QCOMPARE(navigator.nextItem(2), content1); //loop over end of the list
    QCOMPARE(navigator.previousItem(), content2);
    QCOMPARE(navigator.previousItem(2), content1);

    navigator.jump(1);
    QCOMPARE(navigator.currentPosition(), 1);
    QCOMPARE(navigator.currentItem(), content2);
    QCOMPARE(navigator.nextItem(), content1);
    QCOMPARE(navigator.nextItem(2), content2);
    QCOMPARE(navigator.previousItem(), content1);
    QCOMPARE(navigator.previousItem(2), content2);

    navigator.jump(0);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 0);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), 0);
}

void tst_QMediaPlaylistNavigator::currentItemOnce()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::CurrentItemOnce);

    QCOMPARE(navigator.playbackMode(), QMediaPlaylist::CurrentItemOnce);
    QCOMPARE(navigator.currentPosition(), -1);

    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///1"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///2"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///3"))));

    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);

    navigator.jump(1);
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.jump(1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), -1);
}

void tst_QMediaPlaylistNavigator::currentItemInLoop()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);

    QCOMPARE(navigator.playbackMode(), QMediaPlaylist::CurrentItemInLoop);
    QCOMPARE(navigator.currentPosition(), -1);

    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///1"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///2"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///3"))));

    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.jump(1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), 1);
}

void tst_QMediaPlaylistNavigator::randomPlayback()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::Random);

    QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
    QCOMPARE(navigator.currentPosition(), -1);

    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///1"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///2"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///3"))));

    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();
    int pos1 = navigator.currentPosition();
    navigator.next();
    int pos2 = navigator.currentPosition();
    navigator.next();
    int pos3 = navigator.currentPosition();

    QVERIFY(pos1 != -1);
    QVERIFY(pos2 != -1);
    QVERIFY(pos3 != -1);

    navigator.previous();
    QCOMPARE(navigator.currentPosition(), pos2);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), pos3);
    navigator.next();
    int pos4 = navigator.currentPosition();
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), pos3);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), pos2);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), pos1);
    navigator.previous();
    int pos0 = navigator.currentPosition();
    QVERIFY(pos0 != -1);
    navigator.next();
    navigator.next();
    navigator.next();
    navigator.next();
    QCOMPARE(navigator.currentPosition(), pos4);

}

QTEST_MAIN(tst_QMediaPlaylistNavigator)
#include "tst_qmediaplaylistnavigator.moc"
<commit_msg>Update to unit test for QLocalMediaPlaylistProvider. added shuffle() function to unit test.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>
#include <QDebug>
#include "multimedia/qlocalmediaplaylistprovider.h"
#include "multimedia/qmediaplaylistnavigator.h"

class tst_QMediaPlaylistNavigator : public QObject
{
    Q_OBJECT
public slots:
    void init();
    void cleanup();

private slots:
    void construction();
    void setPlaylist();
    void linearPlayback();
    void loopPlayback();
    void currentItemOnce();
    void currentItemInLoop();
    void randomPlayback();
};

void tst_QMediaPlaylistNavigator::init()
{
}

void tst_QMediaPlaylistNavigator::cleanup()
{
}

void tst_QMediaPlaylistNavigator::construction()
{
    QLocalMediaPlaylistProvider playlist;
    QCOMPARE(playlist.size(), 0);

    QMediaPlaylistNavigator navigator(&playlist);
    QVERIFY(navigator.currentItem().isNull());
    QCOMPARE(navigator.currentPosition(), -1);
}

void tst_QMediaPlaylistNavigator::setPlaylist()
{
    QMediaPlaylistNavigator navigator(0);
    QVERIFY(navigator.playlist() != 0);
    QCOMPARE(navigator.playlist()->size(), 0);
    QVERIFY(navigator.playlist()->isReadOnly() );

    QLocalMediaPlaylistProvider playlist;
    QCOMPARE(playlist.size(), 0);

    navigator.setPlaylist(&playlist);
    QCOMPARE(navigator.playlist(), &playlist);
    QCOMPARE(navigator.playlist()->size(), 0);
    QVERIFY(!navigator.playlist()->isReadOnly() );
}

void tst_QMediaPlaylistNavigator::linearPlayback()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::Linear);
    QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range ");
    navigator.jump(0);//it's ok to have warning here
    QVERIFY(navigator.currentItem().isNull());
    QCOMPARE(navigator.currentPosition(), -1);

    QMediaContent content1(QUrl(QLatin1String("file:///1")));
    playlist.appendItem(content1);
    navigator.jump(0);
    QVERIFY(!navigator.currentItem().isNull());

    QCOMPARE(navigator.currentPosition(), 0);
    QCOMPARE(navigator.currentItem(), content1);
    QCOMPARE(navigator.nextItem(), QMediaContent());
    QCOMPARE(navigator.nextItem(2), QMediaContent());
    QCOMPARE(navigator.previousItem(), QMediaContent());
    QCOMPARE(navigator.previousItem(2), QMediaContent());

    QMediaContent content2(QUrl(QLatin1String("file:///2")));
    playlist.appendItem(content2);
    QCOMPARE(navigator.currentPosition(), 0);
    QCOMPARE(navigator.currentItem(), content1);
    QCOMPARE(navigator.nextItem(), content2);
    QCOMPARE(navigator.nextItem(2), QMediaContent());
    QCOMPARE(navigator.previousItem(), QMediaContent());
    QCOMPARE(navigator.previousItem(2), QMediaContent());

    navigator.jump(1);
    QCOMPARE(navigator.currentPosition(), 1);
    QCOMPARE(navigator.currentItem(), content2);
    QCOMPARE(navigator.nextItem(), QMediaContent());
    QCOMPARE(navigator.nextItem(2), QMediaContent());
    QCOMPARE(navigator.previousItem(), content1);
    QCOMPARE(navigator.previousItem(2), QMediaContent());

    navigator.jump(0);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();//jump to the first item
    QCOMPARE(navigator.currentPosition(), 0);

    navigator.previous();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.previous();//jump to the last item
    QCOMPARE(navigator.currentPosition(), 1);
}

void tst_QMediaPlaylistNavigator::loopPlayback()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::Loop);
    QTest::ignoreMessage(QtWarningMsg, "QMediaPlaylistNavigator: Jump outside playlist range ");
    navigator.jump(0);
    QVERIFY(navigator.currentItem().isNull());
    QCOMPARE(navigator.currentPosition(), -1);

    QMediaContent content1(QUrl(QLatin1String("file:///1")));
    playlist.appendItem(content1);
    navigator.jump(0);
    QVERIFY(!navigator.currentItem().isNull());

    QCOMPARE(navigator.currentPosition(), 0);
    QCOMPARE(navigator.currentItem(), content1);
    QCOMPARE(navigator.nextItem(), content1);
    QCOMPARE(navigator.nextItem(2), content1);
    QCOMPARE(navigator.previousItem(), content1);
    QCOMPARE(navigator.previousItem(2), content1);

    QMediaContent content2(QUrl(QLatin1String("file:///2")));
    playlist.appendItem(content2);
    QCOMPARE(navigator.currentPosition(), 0);
    QCOMPARE(navigator.currentItem(), content1);
    QCOMPARE(navigator.nextItem(), content2);
    QCOMPARE(navigator.nextItem(2), content1); //loop over end of the list
    QCOMPARE(navigator.previousItem(), content2);
    QCOMPARE(navigator.previousItem(2), content1);

    navigator.jump(1);
    QCOMPARE(navigator.currentPosition(), 1);
    QCOMPARE(navigator.currentItem(), content2);
    QCOMPARE(navigator.nextItem(), content1);
    QCOMPARE(navigator.nextItem(2), content2);
    QCOMPARE(navigator.previousItem(), content1);
    QCOMPARE(navigator.previousItem(2), content2);

    navigator.jump(0);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 0);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), 0);
}

void tst_QMediaPlaylistNavigator::currentItemOnce()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::CurrentItemOnce);

    QCOMPARE(navigator.playbackMode(), QMediaPlaylist::CurrentItemOnce);
    QCOMPARE(navigator.currentPosition(), -1);

    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///1"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///2"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///3"))));

    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);

    navigator.jump(1);
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.jump(1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), -1);
}

void tst_QMediaPlaylistNavigator::currentItemInLoop()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);

    QCOMPARE(navigator.playbackMode(), QMediaPlaylist::CurrentItemInLoop);
    QCOMPARE(navigator.currentPosition(), -1);

    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///1"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///2"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///3"))));

    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), -1);
    navigator.jump(1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), 1);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), 1);
}

void tst_QMediaPlaylistNavigator::randomPlayback()
{
    QLocalMediaPlaylistProvider playlist;
    QMediaPlaylistNavigator navigator(&playlist);

    navigator.setPlaybackMode(QMediaPlaylist::Random);

    QCOMPARE(navigator.playbackMode(), QMediaPlaylist::Random);
    QCOMPARE(navigator.currentPosition(), -1);

    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///1"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///2"))));
    playlist.appendItem(QMediaContent(QUrl(QLatin1String("file:///3"))));

    playlist.shuffle();

    QCOMPARE(navigator.currentPosition(), -1);
    navigator.next();
    int pos1 = navigator.currentPosition();
    navigator.next();
    int pos2 = navigator.currentPosition();
    navigator.next();
    int pos3 = navigator.currentPosition();

    QVERIFY(pos1 != -1);
    QVERIFY(pos2 != -1);
    QVERIFY(pos3 != -1);

    navigator.previous();
    QCOMPARE(navigator.currentPosition(), pos2);
    navigator.next();
    QCOMPARE(navigator.currentPosition(), pos3);
    navigator.next();
    int pos4 = navigator.currentPosition();
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), pos3);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), pos2);
    navigator.previous();
    QCOMPARE(navigator.currentPosition(), pos1);
    navigator.previous();
    int pos0 = navigator.currentPosition();
    QVERIFY(pos0 != -1);
    navigator.next();
    navigator.next();
    navigator.next();
    navigator.next();
    QCOMPARE(navigator.currentPosition(), pos4);

}

QTEST_MAIN(tst_QMediaPlaylistNavigator)
#include "tst_qmediaplaylistnavigator.moc"
<|endoftext|>


<commit_before>// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// 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 Google Inc. nor the names of its
// contributors 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 <sstream>

#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>

#include <google/protobuf/compiler/ruby/ruby_generator.h>

using google::protobuf::internal::scoped_ptr;

namespace google {
namespace protobuf {
namespace compiler {
namespace ruby {

// Forward decls.
std::string IntToString(uint32_t value);
std::string StripDotProto(const std::string& proto_file);
std::string LabelForField(google::protobuf::FieldDescriptor* field);
std::string TypeName(google::protobuf::FieldDescriptor* field);
void GenerateMessage(const google::protobuf::Descriptor* message,
                     google::protobuf::io::Printer* printer);
void GenerateEnum(const google::protobuf::EnumDescriptor* en,
                  google::protobuf::io::Printer* printer);
void GenerateMessageAssignment(
    const std::string& prefix,
    const google::protobuf::Descriptor* message,
    google::protobuf::io::Printer* printer);
void GenerateEnumAssignment(
    const std::string& prefix,
    const google::protobuf::EnumDescriptor* en,
    google::protobuf::io::Printer* printer);

std::string IntToString(uint32_t value) {
  std::ostringstream os;
  os << value;
  return os.str();
}

std::string StripDotProto(const std::string& proto_file) {
  int lastindex = proto_file.find_last_of(".");
  return proto_file.substr(0, lastindex);
}

std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
  switch (field->label()) {
    case FieldDescriptor::LABEL_OPTIONAL: return "optional";
    case FieldDescriptor::LABEL_REQUIRED: return "required";
    case FieldDescriptor::LABEL_REPEATED: return "repeated";
    default: assert(false); return "";
  }
}

std::string TypeName(const google::protobuf::FieldDescriptor* field) {
  switch (field->cpp_type()) {
    case FieldDescriptor::CPPTYPE_INT32: return "int32";
    case FieldDescriptor::CPPTYPE_INT64: return "int64";
    case FieldDescriptor::CPPTYPE_UINT32: return "uint32";
    case FieldDescriptor::CPPTYPE_UINT64: return "uint64";
    case FieldDescriptor::CPPTYPE_DOUBLE: return "double";
    case FieldDescriptor::CPPTYPE_FLOAT: return "float";
    case FieldDescriptor::CPPTYPE_BOOL: return "bool";
    case FieldDescriptor::CPPTYPE_ENUM: return "enum";
    case FieldDescriptor::CPPTYPE_STRING: return "string";
    case FieldDescriptor::CPPTYPE_MESSAGE: return "message";
    default: assert(false); return "";
  }
}

void GenerateMessage(const google::protobuf::Descriptor* message,
                     google::protobuf::io::Printer* printer) {
  printer->Print(
    "add_message \"$name$\" do\n",
    "name", message->full_name());
  printer->Indent();

  for (int i = 0; i < message->field_count(); i++) {
    const FieldDescriptor* field = message->field(i);
    printer->Print(
      "$label$ :$name$, ",
      "label", LabelForField(field),
      "name", field->name());
    printer->Print(
      ":$type$, $number$",
      "type", TypeName(field),
      "number", IntToString(field->number()));
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
      printer->Print(
        ", \"$subtype$\"\n",
       "subtype", field->message_type()->full_name());
    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
      printer->Print(
        ", \"$subtype$\"\n",
        "subtype", field->enum_type()->full_name());
    } else {
      printer->Print("\n");
    }
  }

  printer->Outdent();
  printer->Print("end\n");

  for (int i = 0; i < message->nested_type_count(); i++) {
    GenerateMessage(message->nested_type(i), printer);
  }
  for (int i = 0; i < message->enum_type_count(); i++) {
    GenerateEnum(message->enum_type(i), printer);
  }
}

void GenerateEnum(const google::protobuf::EnumDescriptor* en,
                  google::protobuf::io::Printer* printer) {
  printer->Print(
    "add_enum \"$name$\" do\n",
    "name", en->full_name());
  printer->Indent();

  for (int i = 0; i < en->value_count(); i++) {
    const EnumValueDescriptor* value = en->value(i);
    printer->Print(
      "value :$name$, $number$\n",
      "name", value->name(),
      "number", IntToString(value->number()));
  }

  printer->Outdent();
  printer->Print(
    "end\n");
}

// Module names, class names, and enum value names need to be Ruby constants,
// which must start with a capital letter.
std::string RubifyConstant(const std::string& name) {
  std::string ret = name;
  if (!ret.empty()) {
    if (ret[0] >= 'a' && ret[0] <= 'z') {
      // If it starts with a lowercase letter, capitalize it.
      ret[0] = ret[0] - 'a' + 'A';
    } else if (ret[0] < 'A' || ret[0] > 'Z') {
      // Otherwise (e.g. if it begins with an underscore), we need to come up
      // with some prefix that starts with a capital letter. We could be smarter
      // here, e.g. try to strip leading underscores, but this may cause other
      // problems if the user really intended the name. So let's just prepend a
      // well-known suffix.
      ret = "PB_" + ret;
    }
  }
  return ret;
}

void GenerateMessageAssignment(
    const std::string& prefix,
    const google::protobuf::Descriptor* message,
    google::protobuf::io::Printer* printer) {
  printer->Print(
    "$prefix$$name$ = ",
    "prefix", prefix,
    "name", RubifyConstant(message->name()));
  printer->Print(
    "Google::Protobuf::DescriptorPool.generated_pool."
    "lookup(\"$full_name$\").msgclass\n",
    "full_name", message->full_name());

  std::string nested_prefix = prefix + message->name() + "::";
  for (int i = 0; i < message->nested_type_count(); i++) {
    GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer);
  }
  for (int i = 0; i < message->enum_type_count(); i++) {
    GenerateEnumAssignment(nested_prefix, message->enum_type(i), printer);
  }
}

void GenerateEnumAssignment(
    const std::string& prefix,
    const google::protobuf::EnumDescriptor* en,
    google::protobuf::io::Printer* printer) {
  printer->Print(
    "$prefix$$name$ = ",
    "prefix", prefix,
    "name", RubifyConstant(en->name()));
  printer->Print(
    "Google::Protobuf::DescriptorPool.generated_pool."
    "lookup(\"$full_name$\").enummodule\n",
    "full_name", en->full_name());
}

int GeneratePackageModules(
    std::string package_name,
    google::protobuf::io::Printer* printer) {
  int levels = 0;
  while (!package_name.empty()) {
    size_t dot_index = package_name.find(".");
    string component;
    if (dot_index == string::npos) {
      component = package_name;
      package_name = "";
    } else {
      component = package_name.substr(0, dot_index);
      package_name = package_name.substr(dot_index + 1);
    }
    component = RubifyConstant(component);
    printer->Print(
      "module $name$\n",
      "name", component);
    printer->Indent();
    levels++;
  }
  return levels;
}

void EndPackageModules(
    int levels,
    google::protobuf::io::Printer* printer) {
  while (levels > 0) {
    levels--;
    printer->Outdent();
    printer->Print(
      "end\n");
  }
}

void GenerateFile(const google::protobuf::FileDescriptor* file,
                  google::protobuf::io::Printer* printer) {
  printer->Print(
    "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
    "# source: $filename$\n"
    "\n",
    "filename", file->name());

  printer->Print(
    "require 'google/protobuf'\n\n");

  for (int i = 0; i < file->dependency_count(); i++) {
    const std::string& name = file->dependency(i)->name();
    printer->Print(
      "require '$name$'\n", "name", StripDotProto(name));
  }

  printer->Print(
    "Google::Protobuf::DescriptorPool.generated_pool.build do\n");
  printer->Indent();
  for (int i = 0; i < file->message_type_count(); i++) {
    GenerateMessage(file->message_type(i), printer);
  }
  for (int i = 0; i < file->enum_type_count(); i++) {
    GenerateEnum(file->enum_type(i), printer);
  }
  printer->Outdent();
  printer->Print(
    "end\n\n");

  int levels = GeneratePackageModules(file->package(), printer);
  for (int i = 0; i < file->message_type_count(); i++) {
    GenerateMessageAssignment("", file->message_type(i), printer);
  }
  for (int i = 0; i < file->enum_type_count(); i++) {
    GenerateEnumAssignment("", file->enum_type(i), printer);
  }
  EndPackageModules(levels, printer);
}

bool Generator::Generate(
    const FileDescriptor* file,
    const string& parameter,
    GeneratorContext* generator_context,
    string* error) const {
  std::string filename =
      StripDotProto(file->name()) + ".rb";
  scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(filename));
  io::Printer printer(output.get(), '$');

  GenerateFile(file, &printer);

  return true;
}

}  // namespace ruby
}  // namespace compiler
}  // namespace protobuf
}  // namespace google
<commit_msg>Support Ruby code generation only for proto3.<commit_after>// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// 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 Google Inc. nor the names of its
// contributors 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 <sstream>

#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream.h>

#include <google/protobuf/compiler/ruby/ruby_generator.h>

using google::protobuf::internal::scoped_ptr;

namespace google {
namespace protobuf {
namespace compiler {
namespace ruby {

// Forward decls.
std::string IntToString(uint32_t value);
std::string StripDotProto(const std::string& proto_file);
std::string LabelForField(google::protobuf::FieldDescriptor* field);
std::string TypeName(google::protobuf::FieldDescriptor* field);
void GenerateMessage(const google::protobuf::Descriptor* message,
                     google::protobuf::io::Printer* printer);
void GenerateEnum(const google::protobuf::EnumDescriptor* en,
                  google::protobuf::io::Printer* printer);
void GenerateMessageAssignment(
    const std::string& prefix,
    const google::protobuf::Descriptor* message,
    google::protobuf::io::Printer* printer);
void GenerateEnumAssignment(
    const std::string& prefix,
    const google::protobuf::EnumDescriptor* en,
    google::protobuf::io::Printer* printer);

std::string IntToString(uint32_t value) {
  std::ostringstream os;
  os << value;
  return os.str();
}

std::string StripDotProto(const std::string& proto_file) {
  int lastindex = proto_file.find_last_of(".");
  return proto_file.substr(0, lastindex);
}

std::string LabelForField(const google::protobuf::FieldDescriptor* field) {
  switch (field->label()) {
    case FieldDescriptor::LABEL_OPTIONAL: return "optional";
    case FieldDescriptor::LABEL_REQUIRED: return "required";
    case FieldDescriptor::LABEL_REPEATED: return "repeated";
    default: assert(false); return "";
  }
}

std::string TypeName(const google::protobuf::FieldDescriptor* field) {
  switch (field->cpp_type()) {
    case FieldDescriptor::CPPTYPE_INT32: return "int32";
    case FieldDescriptor::CPPTYPE_INT64: return "int64";
    case FieldDescriptor::CPPTYPE_UINT32: return "uint32";
    case FieldDescriptor::CPPTYPE_UINT64: return "uint64";
    case FieldDescriptor::CPPTYPE_DOUBLE: return "double";
    case FieldDescriptor::CPPTYPE_FLOAT: return "float";
    case FieldDescriptor::CPPTYPE_BOOL: return "bool";
    case FieldDescriptor::CPPTYPE_ENUM: return "enum";
    case FieldDescriptor::CPPTYPE_STRING: return "string";
    case FieldDescriptor::CPPTYPE_MESSAGE: return "message";
    default: assert(false); return "";
  }
}

void GenerateMessage(const google::protobuf::Descriptor* message,
                     google::protobuf::io::Printer* printer) {
  printer->Print(
    "add_message \"$name$\" do\n",
    "name", message->full_name());
  printer->Indent();

  for (int i = 0; i < message->field_count(); i++) {
    const FieldDescriptor* field = message->field(i);
    printer->Print(
      "$label$ :$name$, ",
      "label", LabelForField(field),
      "name", field->name());
    printer->Print(
      ":$type$, $number$",
      "type", TypeName(field),
      "number", IntToString(field->number()));
    if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
      printer->Print(
        ", \"$subtype$\"\n",
       "subtype", field->message_type()->full_name());
    } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
      printer->Print(
        ", \"$subtype$\"\n",
        "subtype", field->enum_type()->full_name());
    } else {
      printer->Print("\n");
    }
  }

  printer->Outdent();
  printer->Print("end\n");

  for (int i = 0; i < message->nested_type_count(); i++) {
    GenerateMessage(message->nested_type(i), printer);
  }
  for (int i = 0; i < message->enum_type_count(); i++) {
    GenerateEnum(message->enum_type(i), printer);
  }
}

void GenerateEnum(const google::protobuf::EnumDescriptor* en,
                  google::protobuf::io::Printer* printer) {
  printer->Print(
    "add_enum \"$name$\" do\n",
    "name", en->full_name());
  printer->Indent();

  for (int i = 0; i < en->value_count(); i++) {
    const EnumValueDescriptor* value = en->value(i);
    printer->Print(
      "value :$name$, $number$\n",
      "name", value->name(),
      "number", IntToString(value->number()));
  }

  printer->Outdent();
  printer->Print(
    "end\n");
}

// Module names, class names, and enum value names need to be Ruby constants,
// which must start with a capital letter.
std::string RubifyConstant(const std::string& name) {
  std::string ret = name;
  if (!ret.empty()) {
    if (ret[0] >= 'a' && ret[0] <= 'z') {
      // If it starts with a lowercase letter, capitalize it.
      ret[0] = ret[0] - 'a' + 'A';
    } else if (ret[0] < 'A' || ret[0] > 'Z') {
      // Otherwise (e.g. if it begins with an underscore), we need to come up
      // with some prefix that starts with a capital letter. We could be smarter
      // here, e.g. try to strip leading underscores, but this may cause other
      // problems if the user really intended the name. So let's just prepend a
      // well-known suffix.
      ret = "PB_" + ret;
    }
  }
  return ret;
}

void GenerateMessageAssignment(
    const std::string& prefix,
    const google::protobuf::Descriptor* message,
    google::protobuf::io::Printer* printer) {
  printer->Print(
    "$prefix$$name$ = ",
    "prefix", prefix,
    "name", RubifyConstant(message->name()));
  printer->Print(
    "Google::Protobuf::DescriptorPool.generated_pool."
    "lookup(\"$full_name$\").msgclass\n",
    "full_name", message->full_name());

  std::string nested_prefix = prefix + message->name() + "::";
  for (int i = 0; i < message->nested_type_count(); i++) {
    GenerateMessageAssignment(nested_prefix, message->nested_type(i), printer);
  }
  for (int i = 0; i < message->enum_type_count(); i++) {
    GenerateEnumAssignment(nested_prefix, message->enum_type(i), printer);
  }
}

void GenerateEnumAssignment(
    const std::string& prefix,
    const google::protobuf::EnumDescriptor* en,
    google::protobuf::io::Printer* printer) {
  printer->Print(
    "$prefix$$name$ = ",
    "prefix", prefix,
    "name", RubifyConstant(en->name()));
  printer->Print(
    "Google::Protobuf::DescriptorPool.generated_pool."
    "lookup(\"$full_name$\").enummodule\n",
    "full_name", en->full_name());
}

int GeneratePackageModules(
    std::string package_name,
    google::protobuf::io::Printer* printer) {
  int levels = 0;
  while (!package_name.empty()) {
    size_t dot_index = package_name.find(".");
    string component;
    if (dot_index == string::npos) {
      component = package_name;
      package_name = "";
    } else {
      component = package_name.substr(0, dot_index);
      package_name = package_name.substr(dot_index + 1);
    }
    component = RubifyConstant(component);
    printer->Print(
      "module $name$\n",
      "name", component);
    printer->Indent();
    levels++;
  }
  return levels;
}

void EndPackageModules(
    int levels,
    google::protobuf::io::Printer* printer) {
  while (levels > 0) {
    levels--;
    printer->Outdent();
    printer->Print(
      "end\n");
  }
}

void GenerateFile(const google::protobuf::FileDescriptor* file,
                  google::protobuf::io::Printer* printer) {
  printer->Print(
    "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
    "# source: $filename$\n"
    "\n",
    "filename", file->name());

  printer->Print(
    "require 'google/protobuf'\n\n");

  for (int i = 0; i < file->dependency_count(); i++) {
    const std::string& name = file->dependency(i)->name();
    printer->Print(
      "require '$name$'\n", "name", StripDotProto(name));
  }

  printer->Print(
    "Google::Protobuf::DescriptorPool.generated_pool.build do\n");
  printer->Indent();
  for (int i = 0; i < file->message_type_count(); i++) {
    GenerateMessage(file->message_type(i), printer);
  }
  for (int i = 0; i < file->enum_type_count(); i++) {
    GenerateEnum(file->enum_type(i), printer);
  }
  printer->Outdent();
  printer->Print(
    "end\n\n");

  int levels = GeneratePackageModules(file->package(), printer);
  for (int i = 0; i < file->message_type_count(); i++) {
    GenerateMessageAssignment("", file->message_type(i), printer);
  }
  for (int i = 0; i < file->enum_type_count(); i++) {
    GenerateEnumAssignment("", file->enum_type(i), printer);
  }
  EndPackageModules(levels, printer);
}

bool Generator::Generate(
    const FileDescriptor* file,
    const string& parameter,
    GeneratorContext* generator_context,
    string* error) const {

  if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
    *error =
        "Can only generate Ruby code for proto3 .proto files.\n"
        "Please add 'syntax = \"proto3\";' to the top of your .proto file.\n";
    return false;
  }

  std::string filename =
      StripDotProto(file->name()) + ".rb";
  scoped_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(filename));
  io::Printer printer(output.get(), '$');

  GenerateFile(file, &printer);

  return true;
}

}  // namespace ruby
}  // namespace compiler
}  // namespace protobuf
}  // namespace google
<|endoftext|>


<commit_before>//
//  File:   GameController.cpp
//  Class:  GameController
//  Author: John Barbero Unenge
//      All code is my own except where credited to others.
//
//  Copyright (c) 2012 Catch22. All Rights Reserved.
//
//  Date:   24/9/12
//

#include "GameController.hpp"
#include "../Helper/Logger.hpp"
#include "../Helper/InputManager.hpp"

GameController::GameController(int width, int height, CLTexture* texture)
{
    Log(LOG_INFO, "GameController", generateCString("GameCon: %ix%i", width, height));

    InputManager::getSharedManager()->addInputListener(this);

    m_renderer = CreateRendererWithOpenGL10();
    m_renderer->init(width, height, texture);
    m_gameModel = new GameModel();
}
GameController::~GameController()
{
    Log(LOG_INFO, "GameController", "Destroyed GameController");
}

void GameController::update(float dt)
{
    m_renderer->update(dt);
    m_gameModel->update(dt);

    m_renderer->render();
}
void GameController::onRotate(DeviceOrientation orientation)
{
    m_renderer->onRotate(orientation);
}

void GameController::didRecieveInputEvent(InputType type, int locX, int locY)
{
	Log(LOG_EVENT, "GameController",  "DidRecieveInputEvent");
    m_gameModel->playerJump();
}
<commit_msg>Added srand to initiate random. (Used by MapGenerator)<commit_after>//
//  File:   GameController.cpp
//  Class:  GameController
//  Author: John Barbero Unenge
//      All code is my own except where credited to others.
//
//  Copyright (c) 2012 Catch22. All Rights Reserved.
//
//  Date:   24/9/12
//

#include "GameController.hpp"
#include "../Helper/Logger.hpp"
#include "../Helper/InputManager.hpp"

GameController::GameController(int width, int height, CLTexture* texture)
{
	srand ( time(NULL) );

    Log(LOG_INFO, "GameController", generateCString("GameCon: %ix%i", width, height));

    InputManager::getSharedManager()->addInputListener(this);

    m_renderer = CreateRendererWithOpenGL10();
    m_renderer->init(width, height, texture);
    m_gameModel = new GameModel();
}
GameController::~GameController()
{
    Log(LOG_INFO, "GameController", "Destroyed GameController");
}

void GameController::update(float dt)
{
    m_renderer->update(dt);
    m_gameModel->update(dt);

    m_renderer->render();
}
void GameController::onRotate(DeviceOrientation orientation)
{
    m_renderer->onRotate(orientation);
}

void GameController::didRecieveInputEvent(InputType type, int locX, int locY)
{
	Log(LOG_EVENT, "GameController",  "DidRecieveInputEvent");
    m_gameModel->playerJump();
}
<|endoftext|>


<commit_before>/**
 * @file
 * @brief Definition of Object base class
 * @copyright Copyright (c) 2017 CERN and the Corryvreckan authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 */

/**
 * @defgroup Objects Objects
 * @brief Collection of objects passed around between modules
 */

#ifndef CORRYVRECKAN_OBJECT_H
#define CORRYVRECKAN_OBJECT_H

#include <string>
#include <vector>
#include "TObject.h"
#include "TTree.h"

namespace corryvreckan {

    /**
     * @ingroup Objects
     * @brief Base class for internal objects
     *
     * Generic base class. Every class which inherits from Object can be placed on the clipboard and written out to file.
     */
    class Object : public TObject {

    public:
        // Constructors and destructors
        Object();
        explicit Object(std::string detectorID);
        explicit Object(double timestamp);
        Object(std::string detectorID, double timestamp);
        ~Object() override;

        // Methods to get member variables
        std::string getDetectorID() { return m_detectorID; }
        std::string detectorID() { return getDetectorID(); }

        double timestamp() { return m_timestamp; }
        void timestamp(double time) { m_timestamp = time; }
        void setTimestamp(double time) { timestamp(time); }

        // Methods to set member variables
        void setDetectorID(std::string detectorID) { m_detectorID = std::move(detectorID); }

    protected:
        // Member variables
        std::string m_detectorID;
        double m_timestamp{0};

        // ROOT I/O class definition - update version number when you change this class!
        ClassDef(Object, 2)
    };

    // Vector type declaration
    using Objects = std::vector<Object*>;
} // namespace corryvreckan

#endif // CORRYVRECKAN_OBJECT_H
<commit_msg>Silence warnings when building dictionary of CorryvreckanWriter: use ClassDefOverride<commit_after>/**
 * @file
 * @brief Definition of Object base class
 * @copyright Copyright (c) 2017 CERN and the Corryvreckan authors.
 * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md".
 * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an
 * Intergovernmental Organization or submit itself to any jurisdiction.
 */

/**
 * @defgroup Objects Objects
 * @brief Collection of objects passed around between modules
 */

#ifndef CORRYVRECKAN_OBJECT_H
#define CORRYVRECKAN_OBJECT_H

#include <string>
#include <vector>
#include "TObject.h"
#include "TTree.h"

namespace corryvreckan {

    /**
     * @ingroup Objects
     * @brief Base class for internal objects
     *
     * Generic base class. Every class which inherits from Object can be placed on the clipboard and written out to file.
     */
    class Object : public TObject {

    public:
        // Constructors and destructors
        Object();
        explicit Object(std::string detectorID);
        explicit Object(double timestamp);
        Object(std::string detectorID, double timestamp);
        ~Object() override;

        // Methods to get member variables
        std::string getDetectorID() { return m_detectorID; }
        std::string detectorID() { return getDetectorID(); }

        double timestamp() { return m_timestamp; }
        void timestamp(double time) { m_timestamp = time; }
        void setTimestamp(double time) { timestamp(time); }

        // Methods to set member variables
        void setDetectorID(std::string detectorID) { m_detectorID = std::move(detectorID); }

    protected:
        // Member variables
        std::string m_detectorID;
        double m_timestamp{0};

        // ROOT I/O class definition - update version number when you change this class!
        ClassDefOverride(Object, 2)
    };

    // Vector type declaration
    using Objects = std::vector<Object*>;
} // namespace corryvreckan

#endif // CORRYVRECKAN_OBJECT_H
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/fastos/fastos.h>
#include <iostream>
#include <string>
#include <cstdlib>

#include <boost/program_options.hpp>
#include <boost/exception/diagnostic_information.hpp>

#include <vespa/fastos/app.h>
#include <vespa/config-zookeepers.h>

#include <vespa/fileacquirer/config-filedistributorrpc.h>
#include <vespa/filedistribution/distributor/config-filedistributor.h>
#include <vespa/filedistribution/model/config-filereferences.h>

#include <vespa/filedistribution/distributor/filedistributortrackerimpl.h>
#include <vespa/filedistribution/distributor/filedownloadermanager.h>
#include <vespa/filedistribution/distributor/filedownloader.h>
#include <vespa/filedistribution/distributor/signalhandling.h>
#include <vespa/filedistribution/distributor/state_server_impl.h>

#include <vespa/filedistribution/model/filedistributionmodelimpl.h>
#include <vespa/filedistribution/rpc/filedistributorrpc.h>
#include <vespa/filedistribution/common/exception.h>
#include <vespa/filedistribution/common/componentsdeleter.h>

namespace {
const char* programName = "filedistributor";
}

#include <vespa/log/log.h>
LOG_SETUP(programName);

using namespace std::literals;

using namespace filedistribution;
using cloud::config::ZookeepersConfig;
using cloud::config::filedistribution::FiledistributorConfig;
using cloud::config::filedistribution::FiledistributorrpcConfig;

class FileDistributor : public config::IFetcherCallback<ZookeepersConfig>,
                        public config::IFetcherCallback<FiledistributorConfig>,
                        public config::IFetcherCallback<FiledistributorrpcConfig>,
                        public config::IGenerationCallback
{
    class Components {
        ComponentsDeleter _componentsDeleter;
    public:
        const std::shared_ptr<ZKFacade> _zk;
        const std::shared_ptr<FileDistributionModelImpl> _model;
        const std::shared_ptr<FileDistributorTrackerImpl> _tracker;
        const std::shared_ptr<FileDownloader> _downloader;
        const FileDownloaderManager::SP _manager;
        const FileDistributorRPC::SP _rpcHandler;
        const std::shared_ptr<StateServerImpl> _stateServer;

    private:
        class GuardedThread {
        public:
            GuardedThread(const GuardedThread &) = delete;
            GuardedThread & operator = (const GuardedThread &) = delete;
            GuardedThread(const std::shared_ptr<FileDownloader> & downloader) :
                _downloader(downloader),
                _thread([downloader=_downloader] () { downloader->runEventLoop(); })
            { }
            ~GuardedThread() {
                _downloader->close();
                if (_thread.joinable()) {
                    _thread.join();
                }
                if ( !_downloader->drained() ) {
                    LOG(error, "The filedownloader did not drain fully. We will just exit quickly and let a restart repair it for us.");
                    std::quick_exit(67);
                }
            }
        private:
            std::shared_ptr<FileDownloader> _downloader;
            std::thread                     _thread;
        };
        std::unique_ptr<GuardedThread> _downloaderEventLoopThread;
        config::ConfigFetcher _configFetcher;

        template <class T>
        typename std::shared_ptr<T> track(T* component) {
            return _componentsDeleter.track(component);
        }

    public:
        Components(const Components &) = delete;
        Components & operator = (const Components &) = delete;

        Components(const config::ConfigUri & configUri,
                   const ZookeepersConfig& zooKeepersConfig,
                   const FiledistributorConfig& fileDistributorConfig,
                   const FiledistributorrpcConfig& rpcConfig)
            :_zk(track(new ZKFacade(zooKeepersConfig.zookeeperserverlist))),
             _model(track(new FileDistributionModelImpl(fileDistributorConfig.hostname, fileDistributorConfig.torrentport, _zk))),
             _tracker(track(new FileDistributorTrackerImpl(_model))),
             _downloader(track(new FileDownloader(_tracker, fileDistributorConfig.hostname, fileDistributorConfig.torrentport,
                                                  boost::filesystem::path(fileDistributorConfig.filedbpath)))),
             _manager(track(new FileDownloaderManager(_downloader, _model))),
             _rpcHandler(track(new FileDistributorRPC(rpcConfig.connectionspec, _manager))),
             _stateServer(track(new StateServerImpl(fileDistributorConfig.stateport))),
             _downloaderEventLoopThread(),
             _configFetcher(configUri.getContext())
        {
            _downloaderEventLoopThread = std::make_unique<GuardedThread>(_downloader);
            _manager->start();
            _rpcHandler->start();

            _tracker->setDownloader(_downloader);
            _configFetcher.subscribe<FilereferencesConfig>(configUri.getConfigId(), _model.get());
            _configFetcher.start();
            updatedConfig(_configFetcher.getGeneration());
        }

        void updatedConfig(int64_t generation) {
            vespalib::ComponentConfigProducer::Config curr("filedistributor", generation);
            _stateServer->myComponents.addConfig(curr);
        }

        ~Components() {
            _configFetcher.close();
            //Do not waste time retrying zookeeper operations when going down.
            _zk->disableRetries();

            _downloaderEventLoopThread.reset();
        }

    };

    typedef std::lock_guard<std::mutex> LockGuard;
    std::mutex _configMutex;

    bool _completeReconfigurationNeeded;
    std::unique_ptr<ZookeepersConfig> _zooKeepersConfig;
    std::unique_ptr<FiledistributorConfig> _fileDistributorConfig;
    std::unique_ptr<FiledistributorrpcConfig> _rpcConfig;

    std::unique_ptr<Components> _components;
public:
    FileDistributor(const FileDistributor &) = delete;
    FileDistributor & operator = (const FileDistributor &) = delete;
    FileDistributor()
        : _configMutex(),
          _completeReconfigurationNeeded(false),
          _zooKeepersConfig(),
          _fileDistributorConfig(),
          _rpcConfig(),
          _components()
    { }

    void notifyGenerationChange(int64_t generation) {
        if (_components && ! completeReconfigurationNeeded()) {
            _components->updatedConfig(generation);
        }
    }

    //configure overrides
    void configure(std::unique_ptr<ZookeepersConfig> config) {
        LockGuard guard(_configMutex);
        _zooKeepersConfig = std::move(config);
        _completeReconfigurationNeeded = true;
    }

    void configure(std::unique_ptr<FiledistributorConfig> config) {
        LockGuard guard(_configMutex);
        if (_fileDistributorConfig.get() != NULL &&
            (config->torrentport != _fileDistributorConfig->torrentport ||
             config->stateport   != _fileDistributorConfig->stateport ||
             config->hostname    != _fileDistributorConfig->hostname ||
             config->filedbpath  != _fileDistributorConfig->filedbpath))
        {
            _completeReconfigurationNeeded = true;
        } else if (_components.get()) {
            configureSpeedLimits(*config);
        }
        _fileDistributorConfig = std::move(config);

    }

    void configure(std::unique_ptr<FiledistributorrpcConfig> config) {
        LockGuard guard(_configMutex);
        _rpcConfig = std::move(config);
        _completeReconfigurationNeeded = true;
    }

    void run(const config::ConfigUri & configUri) {
        while (!askedToShutDown()) {
            clearReinitializeFlag();
            runImpl(configUri);
        }
    }

    void createComponents(const config::ConfigUri & configUri) {
        LockGuard guard(_configMutex);
        _components.reset(
                new Components(configUri,
                        *_zooKeepersConfig,
                        *_fileDistributorConfig,
                        *_rpcConfig));

        configureSpeedLimits(*_fileDistributorConfig);
        _completeReconfigurationNeeded = false;
    }

    bool completeReconfigurationNeeded() {
        LockGuard guard(_configMutex);
        if (_completeReconfigurationNeeded) {
            LOG(debug, "Complete reconfiguration needed");
        }
        return _completeReconfigurationNeeded;
    }

    void configureSpeedLimits(const FiledistributorConfig& config) {
        FileDownloader& downloader = *_components->_downloader;
        downloader.setMaxDownloadSpeed(config.maxdownloadspeed);
        downloader.setMaxUploadSpeed(config.maxuploadspeed);
    }

    void runImpl(const config::ConfigUri & configUri) {
        createComponents(configUri);

        // We do not want back to back reinitializing as it gives zero time for serving
        // some torrents.
        int postPoneAskedToReinitializedSecs = 50;

        while (!askedToShutDown() &&
	       (postPoneAskedToReinitializedSecs > 0 || !askedToReinitialize()) &&
	       !completeReconfigurationNeeded())
        {
	    postPoneAskedToReinitializedSecs--;
	    std::this_thread::sleep_for(1s);
        }
        _components.reset();
    }
};

class FileDistributorApplication : public FastOS_Application {
    const config::ConfigUri _configUri;
public:
    FileDistributorApplication(const config::ConfigUri & configUri);

    //overrides
    int Main();
};

namespace {

struct ProgramOptionException {
    std::string _msg;
    ProgramOptionException(const std::string & msg)
        : _msg(msg)
    {}
};

bool exists(const std::string& optionName, const boost::program_options::variables_map& map) {
    return map.find(optionName) != map.end();
}

void ensureExists(const std::string& optionName, const boost::program_options::variables_map& map \
                  ) {
    if (!exists(optionName, map)) {
        throw ProgramOptionException("Error: Missing option " + optionName);
    }
}

} //anonymous namespace

FileDistributorApplication::FileDistributorApplication(const config::ConfigUri & configUri)
    :_configUri(configUri) {
}

int
FileDistributorApplication::Main() {
    try {
        FileDistributor distributor;

        config::ConfigFetcher configFetcher(_configUri.getContext());
        configFetcher.subscribe<ZookeepersConfig>(_configUri.getConfigId(), &distributor);
        configFetcher.subscribe<FiledistributorConfig>(_configUri.getConfigId(), &distributor);
        configFetcher.subscribe<FiledistributorrpcConfig>(_configUri.getConfigId(), &distributor);
        configFetcher.subscribeGenerationChanges(&distributor);
        configFetcher.start();

        distributor.run(_configUri);

        EV_STOPPING(programName, "Clean exit");
        return 0;
    } catch(const FileDoesNotExistException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 1;
    } catch(const ZKNodeDoesNotExistsException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 2;
    } catch(const ZKSessionExpired & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 3;
    } catch(const config::ConfigTimeoutException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 4;
    } catch(const vespalib::PortListenException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 5;
    } catch(const ZKConnectionLossException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 6;
    } catch(const ZKGenericException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 99;
    }
}

int
executeApplication(int argc, char** argv) {
    const char
        *configId("configid"),
        *help("help");

    namespace po = boost::program_options;
    po::options_description description;
    description.add_options()
        (configId, po::value<std::string > (), "id to request config for")
        (help, "help");

    try {
        po::variables_map values;
        po::store(
                po::parse_command_line(argc, argv, description),
                values);

        if (exists(help, values)) {
            std::cout <<description;
            return 0;
        }
        ensureExists(configId, values);

        FileDistributorApplication application(
                values[configId].as<std::string > ());
        return application.Entry(argc, argv);

    } catch(ProgramOptionException& e) {
        std::cerr <<e._msg <<std::endl;
        return -1;
    }
}

namespace {

class InitSignals {
public:
    InitSignals() { initSignals(); }
};

InitSignals _G_initSignals __attribute__ ((init_priority (101)));

}

int
main(int argc, char** argv) {
    if (askedToShutDown()) { return 0; }
    EV_STARTED(programName);

    std::srand(std::time(0));
    filedistribution::ZKLogging loggingGuard;

    return executeApplication(argc, argv);
}
<commit_msg>Use existing typedef.<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/fastos/fastos.h>
#include <iostream>
#include <string>
#include <cstdlib>

#include <boost/program_options.hpp>
#include <boost/exception/diagnostic_information.hpp>

#include <vespa/fastos/app.h>
#include <vespa/config-zookeepers.h>

#include <vespa/fileacquirer/config-filedistributorrpc.h>
#include <vespa/filedistribution/distributor/config-filedistributor.h>
#include <vespa/filedistribution/model/config-filereferences.h>

#include <vespa/filedistribution/distributor/filedistributortrackerimpl.h>
#include <vespa/filedistribution/distributor/filedownloadermanager.h>
#include <vespa/filedistribution/distributor/filedownloader.h>
#include <vespa/filedistribution/distributor/signalhandling.h>
#include <vespa/filedistribution/distributor/state_server_impl.h>

#include <vespa/filedistribution/model/filedistributionmodelimpl.h>
#include <vespa/filedistribution/rpc/filedistributorrpc.h>
#include <vespa/filedistribution/common/exception.h>
#include <vespa/filedistribution/common/componentsdeleter.h>

namespace {
const char* programName = "filedistributor";
}

#include <vespa/log/log.h>
LOG_SETUP(programName);

using namespace std::literals;

using namespace filedistribution;
using cloud::config::ZookeepersConfig;
using cloud::config::filedistribution::FiledistributorConfig;
using cloud::config::filedistribution::FiledistributorrpcConfig;

class FileDistributor : public config::IFetcherCallback<ZookeepersConfig>,
                        public config::IFetcherCallback<FiledistributorConfig>,
                        public config::IFetcherCallback<FiledistributorrpcConfig>,
                        public config::IGenerationCallback
{
    class Components {
        ComponentsDeleter _componentsDeleter;
    public:
        const std::shared_ptr<ZKFacade> _zk;
        const std::shared_ptr<FileDistributionModelImpl> _model;
        const std::shared_ptr<FileDistributorTrackerImpl> _tracker;
        const std::shared_ptr<FileDownloader> _downloader;
        const FileDownloaderManager::SP _manager;
        const FileDistributorRPC::SP _rpcHandler;
        const std::shared_ptr<StateServerImpl> _stateServer;

    private:
        class GuardedThread {
        public:
            GuardedThread(const GuardedThread &) = delete;
            GuardedThread & operator = (const GuardedThread &) = delete;
            GuardedThread(const std::shared_ptr<FileDownloader> & downloader) :
                _downloader(downloader),
                _thread([downloader=_downloader] () { downloader->runEventLoop(); })
            { }
            ~GuardedThread() {
                _downloader->close();
                if (_thread.joinable()) {
                    _thread.join();
                }
                if ( !_downloader->drained() ) {
                    LOG(error, "The filedownloader did not drain fully. We will just exit quickly and let a restart repair it for us.");
                    std::quick_exit(67);
                }
            }
        private:
            std::shared_ptr<FileDownloader> _downloader;
            std::thread                     _thread;
        };
        std::unique_ptr<GuardedThread> _downloaderEventLoopThread;
        config::ConfigFetcher _configFetcher;

        template <class T>
        typename std::shared_ptr<T> track(T* component) {
            return _componentsDeleter.track(component);
        }

    public:
        Components(const Components &) = delete;
        Components & operator = (const Components &) = delete;

        Components(const config::ConfigUri & configUri,
                   const ZookeepersConfig& zooKeepersConfig,
                   const FiledistributorConfig& fileDistributorConfig,
                   const FiledistributorrpcConfig& rpcConfig)
            :_zk(track(new ZKFacade(zooKeepersConfig.zookeeperserverlist))),
             _model(track(new FileDistributionModelImpl(fileDistributorConfig.hostname, fileDistributorConfig.torrentport, _zk))),
             _tracker(track(new FileDistributorTrackerImpl(_model))),
             _downloader(track(new FileDownloader(_tracker, fileDistributorConfig.hostname, fileDistributorConfig.torrentport, Path(fileDistributorConfig.filedbpath)))),
             _manager(track(new FileDownloaderManager(_downloader, _model))),
             _rpcHandler(track(new FileDistributorRPC(rpcConfig.connectionspec, _manager))),
             _stateServer(track(new StateServerImpl(fileDistributorConfig.stateport))),
             _downloaderEventLoopThread(),
             _configFetcher(configUri.getContext())
        {
            _downloaderEventLoopThread = std::make_unique<GuardedThread>(_downloader);
            _manager->start();
            _rpcHandler->start();

            _tracker->setDownloader(_downloader);
            _configFetcher.subscribe<FilereferencesConfig>(configUri.getConfigId(), _model.get());
            _configFetcher.start();
            updatedConfig(_configFetcher.getGeneration());
        }

        void updatedConfig(int64_t generation) {
            vespalib::ComponentConfigProducer::Config curr("filedistributor", generation);
            _stateServer->myComponents.addConfig(curr);
        }

        ~Components() {
            _configFetcher.close();
            //Do not waste time retrying zookeeper operations when going down.
            _zk->disableRetries();

            _downloaderEventLoopThread.reset();
        }

    };

    typedef std::lock_guard<std::mutex> LockGuard;
    std::mutex _configMutex;

    bool _completeReconfigurationNeeded;
    std::unique_ptr<ZookeepersConfig> _zooKeepersConfig;
    std::unique_ptr<FiledistributorConfig> _fileDistributorConfig;
    std::unique_ptr<FiledistributorrpcConfig> _rpcConfig;

    std::unique_ptr<Components> _components;
public:
    FileDistributor(const FileDistributor &) = delete;
    FileDistributor & operator = (const FileDistributor &) = delete;
    FileDistributor()
        : _configMutex(),
          _completeReconfigurationNeeded(false),
          _zooKeepersConfig(),
          _fileDistributorConfig(),
          _rpcConfig(),
          _components()
    { }

    void notifyGenerationChange(int64_t generation) {
        if (_components && ! completeReconfigurationNeeded()) {
            _components->updatedConfig(generation);
        }
    }

    //configure overrides
    void configure(std::unique_ptr<ZookeepersConfig> config) {
        LockGuard guard(_configMutex);
        _zooKeepersConfig = std::move(config);
        _completeReconfigurationNeeded = true;
    }

    void configure(std::unique_ptr<FiledistributorConfig> config) {
        LockGuard guard(_configMutex);
        if (_fileDistributorConfig.get() != NULL &&
            (config->torrentport != _fileDistributorConfig->torrentport ||
             config->stateport   != _fileDistributorConfig->stateport ||
             config->hostname    != _fileDistributorConfig->hostname ||
             config->filedbpath  != _fileDistributorConfig->filedbpath))
        {
            _completeReconfigurationNeeded = true;
        } else if (_components.get()) {
            configureSpeedLimits(*config);
        }
        _fileDistributorConfig = std::move(config);

    }

    void configure(std::unique_ptr<FiledistributorrpcConfig> config) {
        LockGuard guard(_configMutex);
        _rpcConfig = std::move(config);
        _completeReconfigurationNeeded = true;
    }

    void run(const config::ConfigUri & configUri) {
        while (!askedToShutDown()) {
            clearReinitializeFlag();
            runImpl(configUri);
        }
    }

    void createComponents(const config::ConfigUri & configUri) {
        LockGuard guard(_configMutex);
        _components.reset(
                new Components(configUri,
                        *_zooKeepersConfig,
                        *_fileDistributorConfig,
                        *_rpcConfig));

        configureSpeedLimits(*_fileDistributorConfig);
        _completeReconfigurationNeeded = false;
    }

    bool completeReconfigurationNeeded() {
        LockGuard guard(_configMutex);
        if (_completeReconfigurationNeeded) {
            LOG(debug, "Complete reconfiguration needed");
        }
        return _completeReconfigurationNeeded;
    }

    void configureSpeedLimits(const FiledistributorConfig& config) {
        FileDownloader& downloader = *_components->_downloader;
        downloader.setMaxDownloadSpeed(config.maxdownloadspeed);
        downloader.setMaxUploadSpeed(config.maxuploadspeed);
    }

    void runImpl(const config::ConfigUri & configUri) {
        createComponents(configUri);

        // We do not want back to back reinitializing as it gives zero time for serving
        // some torrents.
        int postPoneAskedToReinitializedSecs = 50;

        while (!askedToShutDown() &&
	       (postPoneAskedToReinitializedSecs > 0 || !askedToReinitialize()) &&
	       !completeReconfigurationNeeded())
        {
	    postPoneAskedToReinitializedSecs--;
	    std::this_thread::sleep_for(1s);
        }
        _components.reset();
    }
};

class FileDistributorApplication : public FastOS_Application {
    const config::ConfigUri _configUri;
public:
    FileDistributorApplication(const config::ConfigUri & configUri);

    //overrides
    int Main();
};

namespace {

struct ProgramOptionException {
    std::string _msg;
    ProgramOptionException(const std::string & msg)
        : _msg(msg)
    {}
};

bool exists(const std::string& optionName, const boost::program_options::variables_map& map) {
    return map.find(optionName) != map.end();
}

void ensureExists(const std::string& optionName, const boost::program_options::variables_map& map \
                  ) {
    if (!exists(optionName, map)) {
        throw ProgramOptionException("Error: Missing option " + optionName);
    }
}

} //anonymous namespace

FileDistributorApplication::FileDistributorApplication(const config::ConfigUri & configUri)
    :_configUri(configUri) {
}

int
FileDistributorApplication::Main() {
    try {
        FileDistributor distributor;

        config::ConfigFetcher configFetcher(_configUri.getContext());
        configFetcher.subscribe<ZookeepersConfig>(_configUri.getConfigId(), &distributor);
        configFetcher.subscribe<FiledistributorConfig>(_configUri.getConfigId(), &distributor);
        configFetcher.subscribe<FiledistributorrpcConfig>(_configUri.getConfigId(), &distributor);
        configFetcher.subscribeGenerationChanges(&distributor);
        configFetcher.start();

        distributor.run(_configUri);

        EV_STOPPING(programName, "Clean exit");
        return 0;
    } catch(const FileDoesNotExistException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 1;
    } catch(const ZKNodeDoesNotExistsException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 2;
    } catch(const ZKSessionExpired & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 3;
    } catch(const config::ConfigTimeoutException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 4;
    } catch(const vespalib::PortListenException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 5;
    } catch(const ZKConnectionLossException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 6;
    } catch(const ZKGenericException & e) {
        std::string s = boost::diagnostic_information(e);
        EV_STOPPING(programName, s.c_str());
        return 99;
    }
}

int
executeApplication(int argc, char** argv) {
    const char
        *configId("configid"),
        *help("help");

    namespace po = boost::program_options;
    po::options_description description;
    description.add_options()
        (configId, po::value<std::string > (), "id to request config for")
        (help, "help");

    try {
        po::variables_map values;
        po::store(
                po::parse_command_line(argc, argv, description),
                values);

        if (exists(help, values)) {
            std::cout <<description;
            return 0;
        }
        ensureExists(configId, values);

        FileDistributorApplication application(
                values[configId].as<std::string > ());
        return application.Entry(argc, argv);

    } catch(ProgramOptionException& e) {
        std::cerr <<e._msg <<std::endl;
        return -1;
    }
}

namespace {

class InitSignals {
public:
    InitSignals() { initSignals(); }
};

InitSignals _G_initSignals __attribute__ ((init_priority (101)));

}

int
main(int argc, char** argv) {
    if (askedToShutDown()) { return 0; }
    EV_STARTED(programName);

    std::srand(std::time(0));
    filedistribution::ZKLogging loggingGuard;

    return executeApplication(argc, argv);
}
<|endoftext|>