<commit_before>/*
 * Copyright (c) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of 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 "config.h"
#include "bindings/core/v8/ScriptCallStackFactory.h"

#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/V8Binding.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/ScriptArguments.h"
#include "core/inspector/ScriptCallFrame.h"
#include "core/inspector/ScriptCallStack.h"
#include "platform/JSONValues.h"
#include "wtf/text/StringBuilder.h"

#include <v8-debug.h>

namespace blink {

class ExecutionContext;

static ScriptCallFrame toScriptCallFrame(v8::Handle<v8::StackFrame> frame)
{
    StringBuilder stringBuilder;
    stringBuilder.appendNumber(frame->GetScriptId());
    String scriptId = stringBuilder.toString();
    String sourceName;
    v8::Local<v8::String> sourceNameValue(frame->GetScriptNameOrSourceURL());
    if (!sourceNameValue.IsEmpty())
        sourceName = toCoreString(sourceNameValue);

    String functionName;
    v8::Local<v8::String> functionNameValue(frame->GetFunctionName());
    if (!functionNameValue.IsEmpty())
        functionName = toCoreString(functionNameValue);

    int sourceLineNumber = frame->GetLineNumber();
    int sourceColumn = frame->GetColumn();
    return ScriptCallFrame(functionName, scriptId, sourceName, sourceLineNumber, sourceColumn);
}

static void toScriptCallFramesVector(v8::Handle<v8::StackTrace> stackTrace, Vector<ScriptCallFrame>& scriptCallFrames, size_t maxStackSize, bool emptyStackIsAllowed, v8::Isolate* isolate)
{
    ASSERT(isolate->InContext());
    int frameCount = stackTrace->GetFrameCount();
    if (frameCount > static_cast<int>(maxStackSize))
        frameCount = maxStackSize;
    for (int i = 0; i < frameCount; i++) {
        v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i);
        scriptCallFrames.append(toScriptCallFrame(stackFrame));
    }
    if (!frameCount && !emptyStackIsAllowed) {
        // Successfully grabbed stack trace, but there are no frames. It may happen in case
        // when a bound function is called from native code for example.
        // Fallback to setting lineNumber to 0, and source and function name to "undefined".
        scriptCallFrames.append(ScriptCallFrame("undefined", "", "undefined", 0));
    }
}

static PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, bool emptyStackIsAllowed, v8::Isolate* isolate)
{
    ASSERT(isolate->InContext());
    v8::HandleScope scope(isolate);
    Vector<ScriptCallFrame> scriptCallFrames;
    toScriptCallFramesVector(stackTrace, scriptCallFrames, maxStackSize, emptyStackIsAllowed, isolate);
    RefPtrWillBeRawPtr<ScriptCallStack> callStack = ScriptCallStack::create(scriptCallFrames);
    if (InspectorInstrumentation::hasFrontends())
        InspectorInstrumentation::appendAsyncCallStack(currentExecutionContext(isolate), callStack.get());
    return callStack.release();
}

PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, v8::Isolate* isolate)
{
    return createScriptCallStack(stackTrace, maxStackSize, true, isolate);
}

PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed)
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    if (!isolate->InContext())
        return nullptr;
    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, stackTraceOptions));
    return createScriptCallStack(stackTrace, maxStackSize, emptyStackIsAllowed, isolate);
}

PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStackForConsole(ScriptState* scriptState, size_t maxStackSize)
{
    size_t stackSize = 1;
    if (InspectorInstrumentation::hasFrontends()) {
        if (InspectorInstrumentation::consoleAgentEnabled(scriptState->executionContext()))
            stackSize = maxStackSize;
    }
    return createScriptCallStack(stackSize);
}

PassRefPtrWillBeRawPtr<ScriptArguments> createScriptArguments(ScriptState* scriptState, const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount)
{
    Vector<ScriptValue> arguments;
    for (int i = skipArgumentCount; i < v8arguments.Length(); ++i)
        arguments.append(ScriptValue(scriptState, v8arguments[i]));

    return ScriptArguments::create(scriptState, arguments);
}

} // namespace blink
<commit_msg>DevTools: Don't append async call stack to console stack when looking only for a top call frame.<commit_after>/*
 * Copyright (c) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of 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 "config.h"
#include "bindings/core/v8/ScriptCallStackFactory.h"

#include "bindings/core/v8/ScriptValue.h"
#include "bindings/core/v8/V8Binding.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/inspector/ScriptArguments.h"
#include "core/inspector/ScriptCallFrame.h"
#include "core/inspector/ScriptCallStack.h"
#include "platform/JSONValues.h"
#include "wtf/text/StringBuilder.h"

#include <v8-debug.h>

namespace blink {

class ExecutionContext;

static ScriptCallFrame toScriptCallFrame(v8::Handle<v8::StackFrame> frame)
{
    StringBuilder stringBuilder;
    stringBuilder.appendNumber(frame->GetScriptId());
    String scriptId = stringBuilder.toString();
    String sourceName;
    v8::Local<v8::String> sourceNameValue(frame->GetScriptNameOrSourceURL());
    if (!sourceNameValue.IsEmpty())
        sourceName = toCoreString(sourceNameValue);

    String functionName;
    v8::Local<v8::String> functionNameValue(frame->GetFunctionName());
    if (!functionNameValue.IsEmpty())
        functionName = toCoreString(functionNameValue);

    int sourceLineNumber = frame->GetLineNumber();
    int sourceColumn = frame->GetColumn();
    return ScriptCallFrame(functionName, scriptId, sourceName, sourceLineNumber, sourceColumn);
}

static void toScriptCallFramesVector(v8::Handle<v8::StackTrace> stackTrace, Vector<ScriptCallFrame>& scriptCallFrames, size_t maxStackSize, bool emptyStackIsAllowed, v8::Isolate* isolate)
{
    ASSERT(isolate->InContext());
    int frameCount = stackTrace->GetFrameCount();
    if (frameCount > static_cast<int>(maxStackSize))
        frameCount = maxStackSize;
    for (int i = 0; i < frameCount; i++) {
        v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i);
        scriptCallFrames.append(toScriptCallFrame(stackFrame));
    }
    if (!frameCount && !emptyStackIsAllowed) {
        // Successfully grabbed stack trace, but there are no frames. It may happen in case
        // when a bound function is called from native code for example.
        // Fallback to setting lineNumber to 0, and source and function name to "undefined".
        scriptCallFrames.append(ScriptCallFrame("undefined", "", "undefined", 0));
    }
}

static PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, bool emptyStackIsAllowed, v8::Isolate* isolate)
{
    ASSERT(isolate->InContext());
    v8::HandleScope scope(isolate);
    Vector<ScriptCallFrame> scriptCallFrames;
    toScriptCallFramesVector(stackTrace, scriptCallFrames, maxStackSize, emptyStackIsAllowed, isolate);
    RefPtrWillBeRawPtr<ScriptCallStack> callStack = ScriptCallStack::create(scriptCallFrames);
    if (InspectorInstrumentation::hasFrontends() && maxStackSize > 1)
        InspectorInstrumentation::appendAsyncCallStack(currentExecutionContext(isolate), callStack.get());
    return callStack.release();
}

PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, v8::Isolate* isolate)
{
    return createScriptCallStack(stackTrace, maxStackSize, true, isolate);
}

PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed)
{
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    if (!isolate->InContext())
        return nullptr;
    v8::HandleScope handleScope(isolate);
    v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, stackTraceOptions));
    return createScriptCallStack(stackTrace, maxStackSize, emptyStackIsAllowed, isolate);
}

PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStackForConsole(ScriptState* scriptState, size_t maxStackSize)
{
    size_t stackSize = 1;
    if (InspectorInstrumentation::hasFrontends()) {
        if (InspectorInstrumentation::consoleAgentEnabled(scriptState->executionContext()))
            stackSize = maxStackSize;
    }
    return createScriptCallStack(stackSize);
}

PassRefPtrWillBeRawPtr<ScriptArguments> createScriptArguments(ScriptState* scriptState, const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount)
{
    Vector<ScriptValue> arguments;
    for (int i = skipArgumentCount; i < v8arguments.Length(); ++i)
        arguments.append(ScriptValue(scriptState, v8arguments[i]));

    return ScriptArguments::create(scriptState, arguments);
}

} // namespace blink
<|endoftext|>


<commit_before>#include <iostream>
#include <ctime>
#include <cstdlib>
#include <RandomNumberGenerator.h>
#include "Sampler.h"
#include "Models/SimpleExample.h"

using namespace std;
using namespace DNest3;

int main()
{
	char choice;
	do
	{
		cout<<"# [O]verwrite or [A]ppend output files? ";
		cin>>choice;
		choice = tolower(choice);
	}while(choice != 'o' && choice != 'a');
	if(choice == 'o')
	{
		int result = system("rm logw_thinned.txt logw.txt sample.txt scalars_thinned.txt scalars.txt");
		if(result == 0)
			cout<<"# Files removed."<<endl;
		else
			cout<<"# Files didn't exist."<<endl;
	}

	// Initialise RNG and seed with time
	RandomNumberGenerator::initialise_instance();
	RandomNumberGenerator::get_instance().set_seed(time(0));

	for(int k=0; k<100; k++)
	{
		Sampler<SimpleExample> s(100, 200, 5000);
		s.initialise();

		for(int i=0; i<50000; i++)
			s.update();
	}

	return 0;
}

<commit_msg>Do 1000 reps<commit_after>#include <iostream>
#include <ctime>
#include <cstdlib>
#include <RandomNumberGenerator.h>
#include "Sampler.h"
#include "Models/SimpleExample.h"

using namespace std;
using namespace DNest3;

int main()
{
	char choice;
	do
	{
		cout<<"# [O]verwrite or [A]ppend output files? ";
		cin>>choice;
		choice = tolower(choice);
	}while(choice != 'o' && choice != 'a');
	if(choice == 'o')
	{
		int result = system("rm logw_thinned.txt logw.txt sample.txt scalars_thinned.txt scalars.txt");
		if(result == 0)
			cout<<"# Files removed."<<endl;
		else
			cout<<"# Files didn't exist."<<endl;
	}

	// Initialise RNG and seed with time
	RandomNumberGenerator::initialise_instance();
	RandomNumberGenerator::get_instance().set_seed(time(0));

	for(int k=0; k<1000; k++)
	{
		Sampler<SimpleExample> s(100, 200, 5000);
		s.initialise();

		for(int i=0; i<50000; i++)
			s.update();
	}

	return 0;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: apitools.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2001-10-30 11:50:53 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif
#ifndef DBACCESS_SHARED_DBASTRINGS_HRC
#include "dbastrings.hrc"
#endif
#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
#include <cppuhelper/typeprovider.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace cppu;
using namespace osl;
using namespace dbaccess;

//==================================================================================
//= various helper functions
//==================================================================================
//============================================================
//= OSubComponent
//============================================================
//--------------------------------------------------------------------------
OSubComponent::OSubComponent(Mutex& _rMutex, const Reference< XInterface > & xParent)
              :OComponentHelper(_rMutex)
              ,m_xParent(xParent)
{
}

// com::sun::star::lang::XTypeProvider
//--------------------------------------------------------------------------
Sequence< Type > OSubComponent::getTypes() throw (RuntimeException)
{
    OTypeCollection aTypes(::getCppuType( (const Reference< XComponent > *)0 ),
                           ::getCppuType( (const Reference< XTypeProvider > *)0 ),
                           ::getCppuType( (const Reference< XWeak > *)0 ));

    return aTypes.getTypes();
}

// XInterface
//--------------------------------------------------------------------------
void OSubComponent::acquire() throw ( )
{
    OComponentHelper::acquire();
}

//--------------------------------------------------------------------------
void OSubComponent::release() throw ( )
{
    Reference< XInterface > x( xDelegator );
    if (! x.is())
    {
        if (osl_decrementInterlockedCount( &m_refCount ) == 0)
        {
            if (! rBHelper.bDisposed)
            {
                Reference< XInterface > xHoldAlive( *this );

                // remember the parent
                Reference< XInterface > xParent;
                {
                    MutexGuard aGuard( rBHelper.rMutex );
                    xParent = m_xParent;
                    m_xParent = NULL;
                }

                // First dispose
                dispose();

                // only the alive ref holds the object
                OSL_ENSURE( m_refCount == 1, "OSubComponent::release: invalid ref count!" );

                // release the parent in the ~
                if (xParent.is())
                {
                    MutexGuard aGuard( rBHelper.rMutex );
                    m_xParent = xParent;
                }

                // destroy the object if xHoldAlive decrement the refcount to 0
                return;
            }
        }
        // restore the reference count
        osl_incrementInterlockedCount( &m_refCount );
    }

    // as we cover the job of the componenthelper we use the ...
    OWeakAggObject::release();
}

//--------------------------------------------------------------------------
Any OSubComponent::queryInterface( const Type & rType ) throw(RuntimeException)
{
    Any aReturn;
    if (!rType.equals(::getCppuType(static_cast< Reference< XAggregation >* >(NULL))))
        aReturn = OComponentHelper::queryInterface(rType);

    return aReturn;
}

//--------------------------------------------------------------------------
void OSubComponent::disposing()
{
    MutexGuard aGuard( rBHelper.rMutex );
    m_xParent = NULL;
}

<commit_msg>INTEGRATION: CWS insight01 (1.5.124); FILE MERGED 2004/02/12 16:22:24 oj 1.5.124.1: #111075# fix refcount problem<commit_after>/*************************************************************************
 *
 *  $RCSfile: apitools.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2004-08-02 15:26:10 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif
#ifndef DBACCESS_SHARED_DBASTRINGS_HRC
#include "dbastrings.hrc"
#endif
#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
#include <cppuhelper/typeprovider.hxx>
#endif
#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace cppu;
using namespace osl;
using namespace dbaccess;

//==================================================================================
//= various helper functions
//==================================================================================
//============================================================
//= OSubComponent
//============================================================
//--------------------------------------------------------------------------
OSubComponent::OSubComponent(Mutex& _rMutex, const Reference< XInterface > & xParent)
              :OComponentHelper(_rMutex)
              ,m_xParent(xParent)
{
}

// com::sun::star::lang::XTypeProvider
//--------------------------------------------------------------------------
Sequence< Type > OSubComponent::getTypes() throw (RuntimeException)
{
    OTypeCollection aTypes(::getCppuType( (const Reference< XComponent > *)0 ),
                           ::getCppuType( (const Reference< XTypeProvider > *)0 ),
                           ::getCppuType( (const Reference< XWeak > *)0 ));

    return aTypes.getTypes();
}

// XInterface
//--------------------------------------------------------------------------
void OSubComponent::acquire() throw ( )
{
    OComponentHelper::acquire();
}

//--------------------------------------------------------------------------
void OSubComponent::release() throw ( )
{
    Reference< XInterface > x( xDelegator );
    if (! x.is())
    {
        if (osl_decrementInterlockedCount( &m_refCount ) == 0)
        {
            if (! rBHelper.bDisposed)
            {
                Reference< XInterface > xHoldAlive( *this );

                // remember the parent
                Reference< XInterface > xParent;
                {
                    MutexGuard aGuard( rBHelper.rMutex );
                    xParent = m_xParent;
                    m_xParent = NULL;
                }

                // First dispose
                dispose();

                // only the alive ref holds the object
                OSL_ENSURE( m_refCount == 1, "OSubComponent::release: invalid ref count!" );

                // release the parent in the ~
                if (xParent.is())
                {
                    MutexGuard aGuard( rBHelper.rMutex );
                    m_xParent = xParent;
                }

                // destroy the object if xHoldAlive decrement the refcount to 0
                return;
            }
        }
        // restore the reference count
        osl_incrementInterlockedCount( &m_refCount );
    }

    // as we cover the job of the componenthelper we use the ...
    OWeakAggObject::release();
}

//--------------------------------------------------------------------------
Any OSubComponent::queryInterface( const Type & rType ) throw(RuntimeException)
{
    Any aReturn;
    if (!rType.equals(::getCppuType(static_cast< Reference< XAggregation >* >(NULL))))
        aReturn = OComponentHelper::queryInterface(rType);

    return aReturn;
}

//--------------------------------------------------------------------------
void OSubComponent::disposing()
{
    OComponentHelper::disposing();
    MutexGuard aGuard( rBHelper.rMutex );
    m_xParent = NULL;
}

<|endoftext|>


<commit_before>#pragma once
#include <vector>
#include <array>
#include <string>
#include <functional>

#include <boost/multiprecision/cpp_int.hpp>
#include <boost/algorithm/string/trim.hpp>

#include <fc/variant.hpp>
#include <fc/crypto/base64.hpp>
#include <fc/crypto/hex.hpp>
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/io/datastream.hpp>
#include <fc/time.hpp>
#include <fc/fixed_string.hpp>

#include <fc/reflect/reflect.hpp>

#define N(X) eos::types::string_to_name(#X)

namespace eos { namespace types {
   using namespace boost::multiprecision;

   template<typename... T>
   using Vector       = std::vector<T...>;

   template<typename... T>
   using Array        = std::array<T...>;

   using String        = std::string;
   using Time          = fc::time_point_sec;
   using Signature     = fc::ecc::compact_signature;
   using Checksum      = fc::sha256;
   using FieldName     = fc::fixed_string<>;
   using FixedString32 = fc::fixed_string<fc::array<uint64_t,4>>;// std::tuple<uint64_t,uint64_t,uint64_t,uint64_t>>;
   using FixedString16 = fc::fixed_string<>;
   using TypeName      = FixedString32;;
   using Bytes         = Vector<char>;

   template<size_t Size>
   using UInt = number<cpp_int_backend<Size, Size, unsigned_magnitude, unchecked, void> >;
   template<size_t Size>
   using Int = number<cpp_int_backend<Size, Size, signed_magnitude, unchecked, void> >;

   using UInt8     = UInt<8>;
   using UInt16    = UInt<16>;
   using UInt32    = UInt<32>;
   using UInt64    = UInt<64>;
   using UInt128   = boost::multiprecision::uint128_t;
   using UInt256   = boost::multiprecision::uint256_t;
   using Int8      = int8_t;//Int<8>;  these types are different sizes than native...
   using Int16     = int16_t; //Int<16>;
   using Int32     = int32_t; //Int<32>;
   using Int64     = int64_t; //Int<64>;
   using Int128    = boost::multiprecision::int128_t;
   using Int256    = boost::multiprecision::int256_t;
   using uint128_t = unsigned __int128; /// native clang/gcc 128 intrinisic

   static constexpr char char_to_symbol( char c ) {
      if( c >= 'a' && c <= 'z' )
         return (c - 'a') + 1;
      if( c >= '1' && c <= '5' )
         return (c - '1') + 27;
      return 0;
   }

   static constexpr uint64_t string_to_name( const char* str ) {

      uint32_t len = 0;
      while( str[len] ) ++len;

      uint64_t value = 0;

      for( uint32_t i = 0; i <= 12; ++i ) {
         uint64_t c = 0;
         if( i < len && i <= 12 ) c = char_to_symbol( str[i] );

         if( i < 12 ) {
            c &= 0x1f;
            c <<= 64-5*(i+1);
         }
         else {
            c &= 0x0f;
         }

         value |= c;
      }

      return value;
   }

   struct Name {
      uint64_t value = 0;
      bool valid()const { return true; }
      bool empty()const { return 0 == value; }
      bool good()const  { return !empty() && valid();  }

      Name( const char* str )   { set(str);           }
      Name( const String& str ) { set( str.c_str() ); }

      void set( const char* str ) {
      try {
         const auto len = strnlen(str,14);
         FC_ASSERT( len <= 13 );
         value = string_to_name(str);
      }FC_CAPTURE_AND_RETHROW( (str) ) }

      Name( uint64_t v = 0 ):value(v){
      //   FC_ASSERT( !(v>>(5*12)), "invalid name id" );
      }

      explicit operator String()const {
         static const char* charmap = ".abcdefghijklmnopqrstuvwxyz12345";

         String str(13,'.');

         uint64_t tmp = value;
         for( uint32_t i = 0; i <= 12; ++i ) {
            char c = charmap[tmp & (i == 0 ? 0x0f : 0x1f)];
            str[12-i] = c;
            tmp >>= (i == 0 ? 4 : 5);
         }

         boost::algorithm::trim_right_if( str, []( char c ){ return c == '.'; } );
         return str;
      }
      String toString() const { return String(*this); }

      Name& operator=( uint64_t v ) {
         value = v;
         return *this;
      }

      Name& operator=( const String& n ) {
         value = Name(n).value;
         return *this;
      }
      Name& operator=( const char* n ) {
         value = Name(n).value;
         return *this;
      }

      template<typename Stream>
      friend Stream& operator << ( Stream& out, const Name& n ) {
         return out << String(n);
      }

      friend bool operator < ( const Name& a, const Name& b ) { return a.value < b.value; }
      friend bool operator <= ( const Name& a, const Name& b ) { return a.value <= b.value; }
      friend bool operator > ( const Name& a, const Name& b ) { return a.value > b.value; }
      friend bool operator >=( const Name& a, const Name& b ) { return a.value >= b.value; }
      friend bool operator == ( const Name& a, const Name& b ) { return a.value == b.value; }
      friend bool operator != ( const Name& a, const Name& b ) { return a.value != b.value; }

      operator bool()const            { return value; }
      operator uint64_t()const        { return value; }
   };

   struct Field {
      FieldName name;
      TypeName  type;

      bool operator==(const Field& other) const;
   };

   struct Struct {
      TypeName        name;
      TypeName        base;
      Vector<Field>   fields;

      bool operator==(const Struct& other) const;
   };

   using Fields = Vector<Field>;

   template<typename T>
   struct GetStruct{};

    template<> struct GetStruct<Field> {
        static const Struct& type() {
           static Struct result = { "Field ", "", {
                {"name", "FieldName"},
                {"type", "TypeName"}
              }
           };
           return result;
         }
    };
    template<> struct GetStruct<Struct> {
        static const Struct& type() {
           static Struct result = { "Struct ", "", {
                {"name", "TypeName"},
                {"base", "TypeName"},
                {"fields", "Field[]"}
              }
           };
           return result;
         }
    };

   /// TODO: make sure this works with FC raw
   template<typename Stream, typename Number>
   void fromBinary(Stream& st, boost::multiprecision::number<Number>& value) {
      unsigned char data[(std::numeric_limits<decltype(value)>::digits+1)/8];
      st.read((char*)data, sizeof(data));
      boost::multiprecision::import_bits(value, data, data + sizeof(data), 1);
   }
   template<typename Stream, typename Number>
   void toBinary(Stream& st, const boost::multiprecision::number<Number>& value) {
      unsigned char data[(std::numeric_limits<decltype(value)>::digits+1)/8];
      boost::multiprecision::export_bits(value, data, 1);
      st.write((const char*)data, sizeof(data));
   }

}} // namespace eos::types

namespace fc {
  void to_variant(const eos::types::Name& c, fc::variant& v);
  void from_variant(const fc::variant& v, eos::types::Name& check);
  void to_variant(const std::vector<eos::types::Field>& c, fc::variant& v);
  void from_variant(const fc::variant& v, std::vector<eos::types::Field>& check);
  void to_variant(const std::map<std::string,eos::types::Struct>& c, fc::variant& v);
  void from_variant(const fc::variant& v, std::map<std::string,eos::types::Struct>& check);
}

FC_REFLECT(eos::types::Name, (value))
FC_REFLECT(eos::types::Field, (name)(type))
FC_REFLECT(eos::types::Struct, (name)(base)(fields))
<commit_msg>throw error on name overflow #149<commit_after>#pragma once
#include <vector>
#include <array>
#include <string>
#include <functional>

#include <boost/multiprecision/cpp_int.hpp>
#include <boost/algorithm/string/trim.hpp>

#include <fc/variant.hpp>
#include <fc/crypto/base64.hpp>
#include <fc/crypto/hex.hpp>
#include <fc/crypto/elliptic.hpp>
#include <fc/crypto/sha256.hpp>
#include <fc/io/datastream.hpp>
#include <fc/time.hpp>
#include <fc/fixed_string.hpp>

#include <fc/reflect/reflect.hpp>

#define N(X) eos::types::string_to_name(#X)

namespace eos { namespace types {
   using namespace boost::multiprecision;

   template<typename... T>
   using Vector       = std::vector<T...>;

   template<typename... T>
   using Array        = std::array<T...>;

   using String        = std::string;
   using Time          = fc::time_point_sec;
   using Signature     = fc::ecc::compact_signature;
   using Checksum      = fc::sha256;
   using FieldName     = fc::fixed_string<>;
   using FixedString32 = fc::fixed_string<fc::array<uint64_t,4>>;// std::tuple<uint64_t,uint64_t,uint64_t,uint64_t>>;
   using FixedString16 = fc::fixed_string<>;
   using TypeName      = FixedString32;;
   using Bytes         = Vector<char>;

   template<size_t Size>
   using UInt = number<cpp_int_backend<Size, Size, unsigned_magnitude, unchecked, void> >;
   template<size_t Size>
   using Int = number<cpp_int_backend<Size, Size, signed_magnitude, unchecked, void> >;

   using UInt8     = UInt<8>;
   using UInt16    = UInt<16>;
   using UInt32    = UInt<32>;
   using UInt64    = UInt<64>;
   using UInt128   = boost::multiprecision::uint128_t;
   using UInt256   = boost::multiprecision::uint256_t;
   using Int8      = int8_t;//Int<8>;  these types are different sizes than native...
   using Int16     = int16_t; //Int<16>;
   using Int32     = int32_t; //Int<32>;
   using Int64     = int64_t; //Int<64>;
   using Int128    = boost::multiprecision::int128_t;
   using Int256    = boost::multiprecision::int256_t;
   using uint128_t = unsigned __int128; /// native clang/gcc 128 intrinisic

   static constexpr char char_to_symbol( char c ) {
      if( c >= 'a' && c <= 'z' )
         return (c - 'a') + 1;
      if( c >= '1' && c <= '5' )
         return (c - '1') + 27;
      return 0;
   }

   static constexpr uint64_t string_to_name( const char* str ) {

      uint32_t len = 0;
      while( str[len] ) ++len;

      uint64_t value = 0;

      for( uint32_t i = 0; i <= 12; ++i ) {
         uint64_t c = 0;
         if( i < len && i <= 12 ) c = char_to_symbol( str[i] );

         if( i < 12 ) {
            c &= 0x1f;
            c <<= 64-5*(i+1);
         }
         else {
            c &= 0x0f;
         }

         value |= c;
      }

      return value;
   }

   struct Name {
      uint64_t value = 0;
      bool valid()const { return true; }
      bool empty()const { return 0 == value; }
      bool good()const  { return !empty() && valid();  }

      Name( const char* str )   { set(str);           }
      Name( const String& str ) { set( str.c_str() ); }

      void set( const char* str ) {
      try {
         const auto len = strnlen(str,14);
         FC_ASSERT( len <= 13 );
         value = string_to_name(str);
         FC_ASSERT( toString() == String(str), "name not properly normalized", ("name",String(str))("normalized",toString())  );
      }FC_CAPTURE_AND_RETHROW( (str) ) }

      Name( uint64_t v = 0 ):value(v){}

      explicit operator String()const {
         static const char* charmap = ".abcdefghijklmnopqrstuvwxyz12345";

         String str(13,'.');

         uint64_t tmp = value;
         for( uint32_t i = 0; i <= 12; ++i ) {
            char c = charmap[tmp & (i == 0 ? 0x0f : 0x1f)];
            str[12-i] = c;
            tmp >>= (i == 0 ? 4 : 5);
         }

         boost::algorithm::trim_right_if( str, []( char c ){ return c == '.'; } );
         return str;
      }
      String toString() const { return String(*this); }

      Name& operator=( uint64_t v ) {
         value = v;
         return *this;
      }

      Name& operator=( const String& n ) {
         value = Name(n).value;
         return *this;
      }
      Name& operator=( const char* n ) {
         value = Name(n).value;
         return *this;
      }

      template<typename Stream>
      friend Stream& operator << ( Stream& out, const Name& n ) {
         return out << String(n);
      }

      friend bool operator < ( const Name& a, const Name& b ) { return a.value < b.value; }
      friend bool operator <= ( const Name& a, const Name& b ) { return a.value <= b.value; }
      friend bool operator > ( const Name& a, const Name& b ) { return a.value > b.value; }
      friend bool operator >=( const Name& a, const Name& b ) { return a.value >= b.value; }
      friend bool operator == ( const Name& a, const Name& b ) { return a.value == b.value; }
      friend bool operator != ( const Name& a, const Name& b ) { return a.value != b.value; }

      operator bool()const            { return value; }
      operator uint64_t()const        { return value; }
   };

   struct Field {
      FieldName name;
      TypeName  type;

      bool operator==(const Field& other) const;
   };

   struct Struct {
      TypeName        name;
      TypeName        base;
      Vector<Field>   fields;

      bool operator==(const Struct& other) const;
   };

   using Fields = Vector<Field>;

   template<typename T>
   struct GetStruct{};

    template<> struct GetStruct<Field> {
        static const Struct& type() {
           static Struct result = { "Field ", "", {
                {"name", "FieldName"},
                {"type", "TypeName"}
              }
           };
           return result;
         }
    };
    template<> struct GetStruct<Struct> {
        static const Struct& type() {
           static Struct result = { "Struct ", "", {
                {"name", "TypeName"},
                {"base", "TypeName"},
                {"fields", "Field[]"}
              }
           };
           return result;
         }
    };

   /// TODO: make sure this works with FC raw
   template<typename Stream, typename Number>
   void fromBinary(Stream& st, boost::multiprecision::number<Number>& value) {
      unsigned char data[(std::numeric_limits<decltype(value)>::digits+1)/8];
      st.read((char*)data, sizeof(data));
      boost::multiprecision::import_bits(value, data, data + sizeof(data), 1);
   }
   template<typename Stream, typename Number>
   void toBinary(Stream& st, const boost::multiprecision::number<Number>& value) {
      unsigned char data[(std::numeric_limits<decltype(value)>::digits+1)/8];
      boost::multiprecision::export_bits(value, data, 1);
      st.write((const char*)data, sizeof(data));
   }

}} // namespace eos::types

namespace fc {
  void to_variant(const eos::types::Name& c, fc::variant& v);
  void from_variant(const fc::variant& v, eos::types::Name& check);
  void to_variant(const std::vector<eos::types::Field>& c, fc::variant& v);
  void from_variant(const fc::variant& v, std::vector<eos::types::Field>& check);
  void to_variant(const std::map<std::string,eos::types::Struct>& c, fc::variant& v);
  void from_variant(const fc::variant& v, std::map<std::string,eos::types::Struct>& check);
}

FC_REFLECT(eos::types::Name, (value))
FC_REFLECT(eos::types::Field, (name)(type))
FC_REFLECT(eos::types::Struct, (name)(base)(fields))
<|endoftext|>


<commit_before>/*
    Copyright (C) 2014-2015 Islog

    This file is part of Leosac.

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

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

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

#include <zmqpp/message.hpp>
#include <tools/log.hpp>
#include <core/auth/Auth.hpp>
#include <tools/Colorize.hpp>
#include "NotifierInstance.hpp"
#include "core/auth/WiegandCard.hpp"

using namespace Leosac;
using namespace Leosac::Module;
using namespace Leosac::Module::TCPNotifier;

NotifierInstance::NotifierInstance(zmqpp::context &ctx, zmqpp::reactor &reactor,
                                   std::vector<std::string> auth_sources,
                                   std::vector<std::string> connect_to,
                                   std::vector<std::string> bind_to,
                                   ProtocolHandlerUPtr protocol_handler)
    : bus_sub_(ctx, zmqpp::socket_type::sub)
    , tcp_(ctx, zmqpp::socket_type::stream)
    , protocol_(std::move(protocol_handler))
{
  ASSERT_LOG(connect_to.empty() || bind_to.empty(),
             "Cannot bind and connect at the same time.");
  ASSERT_LOG(!connect_to.empty() || !bind_to.empty(), "Cannot do nothing");
  ASSERT_LOG(protocol_, "No protocol handler");

  act_as_server_ = !bind_to.empty();

  bus_sub_.connect("inproc://zmq-bus-pub");
  reactor.add(bus_sub_, std::bind(&NotifierInstance::handle_msg_bus, this));
  reactor.add(tcp_, std::bind(&NotifierInstance::handle_tcp_msg, this));

  for (const auto &src : auth_sources)
  {
    bus_sub_.subscribe("S_" + src);
  }

  if (act_as_server_)
  {
    for (auto &endpoint : bind_to)
    {
      INFO("TCP-Notifier binding to: tcp://" << endpoint);
      tcp_.bind("tcp://" + endpoint);
    }
  }
  else
  {
    for (auto &endpoint : connect_to)
    {
      TargetInfo target;
      target.url_    = "tcp://" + endpoint;
      target.status_ = false;
      tcp_.connect(target.url_);
      INFO("TCP-Notifier remote target: " << Colorize::green(target.url_));
      tcp_.get(zmqpp::socket_option::identity, target.zmq_identity_);
      targets_.push_back(std::move(target));
    }
  }
}

void NotifierInstance::handle_credential(Leosac::Auth::WiegandCard &card)
{
  for (const auto &target : targets_)
  {
    // Skip disconnected client.
    if (!target.status_)
      continue;
    zmqpp::message msg;

    msg << target.zmq_identity_;
    auto data = protocol_->build_cred_msg(card);
    msg.add_raw(&data[0], data.size());

    auto ret = tcp_.send(msg, true);
    if (ret == false) // would block. woops
    {
      ERROR("Sending to client would block.");
    }
  }
}

void NotifierInstance::handle_tcp_msg()
{
  zmqpp::message msg;

  tcp_.receive(msg);
  std::string routing_id;
  std::string data;

  assert(msg.parts() == 2);
  msg >> routing_id >> data;

  INFO("Received TCP data from client " << routing_id << ", data {" << data
                                        << "}");
  if (data.size() == 0)
  {
    auto target = find_target(routing_id);
    if (!target && act_as_server_)
    {
      TargetInfo ti;
      ti.status_       = true;
      ti.zmq_identity_ = routing_id;

      targets_.push_back(std::move(ti));
      INFO("New client connected to us.");
      return;
    }
    else
      ASSERT_LOG(target, "Why did we lose a target?");

    if (target->status_)
      INFO("Lost connection with client");
    else
      INFO("Successfully connected to client.");

    target->status_ = !target->status_;
  }
}

NotifierInstance::TargetInfo *
NotifierInstance::find_target(const std::string &routing_id)
{
  auto itr = std::find_if(targets_.begin(), targets_.end(),
                          [&](const TargetInfo &target)
                          {
                            return target.zmq_identity_ == routing_id;
                          });
  if (itr != targets_.end())
    return &(*itr);
  return nullptr;
}

void NotifierInstance::handle_msg_bus()
{
  zmqpp::message msg;
  std::string src;
  Leosac::Auth::SourceType type;
  std::string card;
  int bits;

  bus_sub_.receive(msg);
  if (msg.parts() < 4)
  {
    WARN("Unexpected message content.");
    return;
  }
  msg >> src >> type >> card >> bits;
  if (type != Leosac::Auth::SourceType::SIMPLE_WIEGAND)
  {
    INFO("TCP-Notifier cannot handle this type of credential yet.");
    return;
  }
  auto wiegand_card = Auth::WiegandCard(card, bits);

  handle_credential(wiegand_card);
}
<commit_msg>Fix memory leak in TCP-Notifier<commit_after>/*
    Copyright (C) 2014-2015 Islog

    This file is part of Leosac.

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

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

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

#include <zmqpp/message.hpp>
#include <tools/log.hpp>
#include <core/auth/Auth.hpp>
#include <tools/Colorize.hpp>
#include "NotifierInstance.hpp"
#include "core/auth/WiegandCard.hpp"

using namespace Leosac;
using namespace Leosac::Module;
using namespace Leosac::Module::TCPNotifier;

NotifierInstance::NotifierInstance(zmqpp::context &ctx, zmqpp::reactor &reactor,
                                   std::vector<std::string> auth_sources,
                                   std::vector<std::string> connect_to,
                                   std::vector<std::string> bind_to,
                                   ProtocolHandlerUPtr protocol_handler)
    : bus_sub_(ctx, zmqpp::socket_type::sub)
    , tcp_(ctx, zmqpp::socket_type::stream)
    , protocol_(std::move(protocol_handler))
{
  ASSERT_LOG(connect_to.empty() || bind_to.empty(),
             "Cannot bind and connect at the same time.");
  ASSERT_LOG(!connect_to.empty() || !bind_to.empty(), "Cannot do nothing");
  ASSERT_LOG(protocol_, "No protocol handler");

  act_as_server_ = !bind_to.empty();

  bus_sub_.connect("inproc://zmq-bus-pub");
  reactor.add(bus_sub_, std::bind(&NotifierInstance::handle_msg_bus, this));
  reactor.add(tcp_, std::bind(&NotifierInstance::handle_tcp_msg, this));

  for (const auto &src : auth_sources)
  {
    bus_sub_.subscribe("S_" + src);
  }

  if (act_as_server_)
  {
    for (auto &endpoint : bind_to)
    {
      INFO("TCP-Notifier binding to: tcp://" << endpoint);
      tcp_.bind("tcp://" + endpoint);
    }
  }
  else
  {
    for (auto &endpoint : connect_to)
    {
      TargetInfo target;
      target.url_    = "tcp://" + endpoint;
      target.status_ = false;
      tcp_.connect(target.url_);
      INFO("TCP-Notifier remote target: " << Colorize::green(target.url_));
      tcp_.get(zmqpp::socket_option::identity, target.zmq_identity_);
      targets_.push_back(std::move(target));
    }
  }
}

void NotifierInstance::handle_credential(Leosac::Auth::WiegandCard &card)
{
  for (const auto &target : targets_)
  {
    // Skip disconnected client.
    if (!target.status_)
      continue;
    zmqpp::message msg;

    msg << target.zmq_identity_;
    auto data = protocol_->build_cred_msg(card);
    msg.add_raw(&data[0], data.size());

    auto ret = tcp_.send(msg, true);
    if (ret == false) // would block. woops
    {
      ERROR("Sending to client would block.");
    }
  }
}

void NotifierInstance::handle_tcp_msg()
{
  zmqpp::message msg;

  tcp_.receive(msg);
  std::string routing_id;
  std::string data;

  assert(msg.parts() == 2);
  msg >> routing_id >> data;

  INFO("Received TCP data from client " << routing_id << ", data {" << data
                                        << "}");
  if (data.size() == 0)
  {
    auto target = find_target(routing_id);
    if (act_as_server_)
    {
      // As a server we drop disconnected peer, or create TargetInfo
      // for newly connected peer.
      if (!target)
      {
        TargetInfo ti;
        ti.status_       = true;
        ti.zmq_identity_ = routing_id;

        targets_.push_back(std::move(ti));
        INFO("New client connected to us.");
      }
      else
      {
        targets_.erase(std::remove_if(targets_.begin(), targets_.end(),
                                      [&](const TargetInfo &info)
                                      {
                                        return info.zmq_identity_ == routing_id;
                                      }),
                       targets_.end());
      }
      return;
    }
    ASSERT_LOG(target, "Why did we lose a target?");

    if (target->status_)
      INFO("Lost connection with client");
    else
      INFO("Successfully connected to client.");

    target->status_ = !target->status_;
  }
}

NotifierInstance::TargetInfo *
NotifierInstance::find_target(const std::string &routing_id)
{
  auto itr = std::find_if(targets_.begin(), targets_.end(),
                          [&](const TargetInfo &target)
                          {
                            return target.zmq_identity_ == routing_id;
                          });
  if (itr != targets_.end())
    return &(*itr);
  return nullptr;
}

void NotifierInstance::handle_msg_bus()
{
  zmqpp::message msg;
  std::string src;
  Leosac::Auth::SourceType type;
  std::string card;
  int bits;

  bus_sub_.receive(msg);
  if (msg.parts() < 4)
  {
    WARN("Unexpected message content.");
    return;
  }
  msg >> src >> type >> card >> bits;
  if (type != Leosac::Auth::SourceType::SIMPLE_WIEGAND)
  {
    INFO("TCP-Notifier cannot handle this type of credential yet.");
    return;
  }
  auto wiegand_card = Auth::WiegandCard(card, bits);

  handle_credential(wiegand_card);
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/qpointer.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qbasictimer.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qdebug.h>
#include <QtGui/qgraphicsscene.h>
#include <QtGui/qgraphicsview.h>
#include <QtGui/qscrollbar.h>
#include <QtGui/qx11info_x11.h>

#include "qgraphicsvideoitem.h"

#ifdef Q_OS_SYMBIAN
#define QGRAPHICSVIDEOITEM_ROTATION_SUPPORT
#endif

#include <qmediaobject.h>
#include <qmediaservice.h>
#include <qvideowindowcontrol.h>

QT_BEGIN_NAMESPACE

#define DEBUG_GFX_VIDEO_ITEM

class QGraphicsVideoItemPrivate : public QObject
{
public:
    QGraphicsVideoItemPrivate()
        : q_ptr(0)
        , mediaObject(0)
        , service(0)
        , windowControl(0)
        , savedViewportUpdateMode(QGraphicsView::FullViewportUpdate)
        , aspectRatioMode(Qt::KeepAspectRatio)
        , rect(0.0, 0.0, 320, 240)
        , videoWidget(0)
    {
    }

    QGraphicsVideoItem *q_ptr;

    QMediaObject *mediaObject;
    QMediaService *service;
    QVideoWindowControl *windowControl;
    QPointer<QGraphicsView> currentView;
    QList<QPointer<QObject> > eventFilterTargets;
    QGraphicsView::ViewportUpdateMode savedViewportUpdateMode;

    Qt::AspectRatioMode aspectRatioMode;
    QRectF rect;
    QRectF boundingRect;
    QRectF displayRect;
    QSizeF nativeSize;

    QWidget *videoWidget;

    bool eventFilter(QObject *object, QEvent *event);
    void updateEventFilters();

    void setWidget(QWidget *widget);
    void clearService();
    void updateRects();
    void updateLastFrame();

    void _q_present();
    void _q_updateNativeSize();
    void _q_serviceDestroyed();
    void _q_mediaObjectDestroyed();
};

void QGraphicsVideoItemPrivate::_q_present()
{

}

bool QGraphicsVideoItemPrivate::eventFilter(QObject *object, QEvent *event)
{
    if (windowControl && object == videoWidget && QEvent::WinIdChange == event->type()) {
        windowControl->setWinId(videoWidget->effectiveWinId());
    } else {
        bool updateEventFiltersRequired = false;
        bool refreshDisplayRequired = false;
        foreach (QPointer<QObject> target, eventFilterTargets) {
            if (object == target.data()) {
                switch (event->type()) {
                case QEvent::ParentChange:
                    updateEventFiltersRequired = true;
                    refreshDisplayRequired = true;
                    break;
                case QEvent::Move:
                case QEvent::Resize:
                    refreshDisplayRequired = true;
                    break;
                }
            }
        }
        if (updateEventFiltersRequired)
            updateEventFilters();
#ifdef Q_OS_SYMBIAN
        if (refreshDisplayRequired && windowControl)
            QMetaObject::invokeMethod(windowControl, "refreshDisplay");
#endif
    }
    return false;
}

void QGraphicsVideoItemPrivate::setWidget(QWidget *widget)
{
    if (videoWidget != widget) {
        videoWidget = widget;
        if (widget) {
            windowControl->setWinId(widget->winId());
            widget->installEventFilter(this);
        }
    }
}

void QGraphicsVideoItemPrivate::clearService()
{
    if (windowControl) {
        QObject::disconnect(windowControl, SIGNAL(nativeSizeChanged()), q_ptr, SLOT(_q_updateNativeSize()));
        service->releaseControl(windowControl);
        windowControl = 0;
    }

    if (service) {
        QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
        service = 0;
    }
}

void QGraphicsVideoItemPrivate::updateRects()
{
    q_ptr->prepareGeometryChange();
    QSizeF videoSize;
    if (nativeSize.isEmpty()) {
        videoSize = rect.size();
    } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
        videoSize = rect.size();
    } else {
        // KeepAspectRatio or KeepAspectRatioByExpanding
        videoSize = nativeSize;
        videoSize.scale(rect.size(), aspectRatioMode);
    }
    displayRect = QRectF(QPointF(0, 0), videoSize);
    displayRect.moveCenter(rect.center());
    boundingRect = displayRect.intersected(rect);
}

void QGraphicsVideoItemPrivate::updateLastFrame()
{
}

void QGraphicsVideoItemPrivate::updateEventFilters()
{
    // In order to determine when the absolute screen position of the item
    // changes, we need to receive move events sent to m_currentView
    // or any of its ancestors.
    foreach (QPointer<QObject> target, eventFilterTargets)
        if (target)
            target->removeEventFilter(this);
    eventFilterTargets.clear();
    QObject *target = currentView;
    while (target) {
        target->installEventFilter(this);
        eventFilterTargets.append(target);
        target = target->parent();
    }
}

void QGraphicsVideoItemPrivate::_q_updateNativeSize()
{
    const QSize size = windowControl->nativeSize();
    if (nativeSize != size) {
        nativeSize = size;

        updateRects();
        emit q_ptr->nativeSizeChanged(nativeSize);
    }
}

void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
{
    windowControl = 0;
    service = 0;
}

void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed()
{
    mediaObject = 0;

    clearService();
}

QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
    : QGraphicsObject(parent)
    , d_ptr(new QGraphicsVideoItemPrivate)
{
    d_ptr->q_ptr = this;

    setCacheMode(NoCache);
    setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges);
    setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
}

QGraphicsVideoItem::~QGraphicsVideoItem()
{
    if (d_ptr->windowControl) {
        d_ptr->service->releaseControl(d_ptr->windowControl);
    }

    if (d_ptr->currentView)
        d_ptr->currentView->setViewportUpdateMode(d_ptr->savedViewportUpdateMode);

    delete d_ptr;
}

QMediaObject *QGraphicsVideoItem::mediaObject() const
{
    return d_func()->mediaObject;
}

bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
{
    Q_D(QGraphicsVideoItem);

    if (object == d->mediaObject)
        return true;

    d->clearService();

    d->mediaObject = object;

    if (d->mediaObject) {
        d->service = d->mediaObject->service();

        if (d->service) {
            d->windowControl = qobject_cast<QVideoWindowControl *>(
                    d->service->requestControl(QVideoWindowControl_iid));

            if (d->windowControl != 0) {
                connect(d->service, SIGNAL(destroyed()), SLOT(_q_serviceDestroyed()));
                connect(d->windowControl, SIGNAL(nativeSizeChanged()), SLOT(_q_updateNativeSize()));
                d->windowControl->setAspectRatioMode(Qt::IgnoreAspectRatio);
                //d->windowControl->setProperty("colorKey", QVariant(QColor(16,7,2)));
                d->windowControl->setProperty("autopaintColorKey", QVariant(false));

                d->updateRects();
                return true;
            } else {
                qWarning() << "Service doesn't support QVideoWindowControl, overlay item failed";
            }
        }
    }

    d->mediaObject = 0;
    return false;
}

Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
{
    return d_func()->aspectRatioMode;
}

void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
{
    Q_D(QGraphicsVideoItem);

    d->aspectRatioMode = mode;
    d->updateRects();
}

QPointF QGraphicsVideoItem::offset() const
{
    return d_func()->rect.topLeft();
}

void QGraphicsVideoItem::setOffset(const QPointF &offset)
{
    Q_D(QGraphicsVideoItem);

    d->rect.moveTo(offset);
    d->updateRects();
}

QSizeF QGraphicsVideoItem::size() const
{
    return d_func()->rect.size();
}

void QGraphicsVideoItem::setSize(const QSizeF &size)
{
    Q_D(QGraphicsVideoItem);

    d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
    d->updateRects();
}

QSizeF QGraphicsVideoItem::nativeSize() const
{
    return d_func()->nativeSize;
}

QRectF QGraphicsVideoItem::boundingRect() const
{
    return d_func()->boundingRect;
}

void QGraphicsVideoItem::paint(
        QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
#ifdef DEBUG_GFX_VIDEO_ITEM
    qDebug() << "QGraphicsVideoItem::paint";
#endif

    Q_UNUSED(option);
    Q_D(QGraphicsVideoItem);

    QGraphicsView *view = 0;
    if (scene() && !scene()->views().isEmpty())
        view = scene()->views().first();

    //it's necessary to switch vieport update mode to FullViewportUpdate
    //otherwise the video item area can be just scrolled without notifying overlay
    //about geometry changes
    if (view != d->currentView) {
        if (d->currentView) {
            d->currentView->setViewportUpdateMode(d->savedViewportUpdateMode);
        }

        d->currentView = view;
        if (view) {
            d->savedViewportUpdateMode = view->viewportUpdateMode();
            view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
        }
        d->updateEventFilters();
    }

    QColor colorKey = Qt::black;

    if (d->windowControl != 0 && widget != 0) {
        d->setWidget(widget);

        QTransform transform = painter->combinedTransform();
        QRect overlayRect = transform.mapRect(d->displayRect).toRect();
        QRect currentSurfaceRect = d->windowControl->displayRect();

        if (currentSurfaceRect != overlayRect) {
#ifdef DEBUG_GFX_VIDEO_ITEM
            qDebug() << "set video display rect:" << overlayRect;
#endif
            d->windowControl->setDisplayRect(overlayRect);
        }

        colorKey = d->windowControl->property("colorKey").value<QColor>();
#ifdef QGRAPHICSVIDEOITEM_ROTATION_SUPPORT
        const qreal angle = transform.map(QLineF(0, 0, 1, 0)).angle();
        d->windowControl->setProperty("rotation", QVariant::fromValue<qreal>(angle));
#endif
    }

    if (colorKey.alpha() != 255)
        painter->setCompositionMode(QPainter::CompositionMode_Source);
    painter->fillRect(d->boundingRect, colorKey);
}

QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
    Q_D(QGraphicsVideoItem);

    switch (change) {
    case ItemScenePositionHasChanged:
        update(boundingRect());
        break;
    case ItemVisibleChange:
        //move overlay out of the screen if video item becomes invisible
        if (d->windowControl != 0 && !value.toBool())
            d->windowControl->setDisplayRect(QRect(-1,-1,1,1));
        break;
    default:
        break;
    }

    return QGraphicsItem::itemChange(change, value);
}

void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
{
    QGraphicsObject::timerEvent(event);
}

#include "moc_qgraphicsvideoitem.cpp"
QT_END_NAMESPACE
<commit_msg>QtMultimedia: silence compiler warning about unhandled enum values<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/qpointer.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qbasictimer.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qdebug.h>
#include <QtGui/qgraphicsscene.h>
#include <QtGui/qgraphicsview.h>
#include <QtGui/qscrollbar.h>
#include <QtGui/qx11info_x11.h>

#include "qgraphicsvideoitem.h"

#ifdef Q_OS_SYMBIAN
#define QGRAPHICSVIDEOITEM_ROTATION_SUPPORT
#endif

#include <qmediaobject.h>
#include <qmediaservice.h>
#include <qvideowindowcontrol.h>

QT_BEGIN_NAMESPACE

#define DEBUG_GFX_VIDEO_ITEM

class QGraphicsVideoItemPrivate : public QObject
{
public:
    QGraphicsVideoItemPrivate()
        : q_ptr(0)
        , mediaObject(0)
        , service(0)
        , windowControl(0)
        , savedViewportUpdateMode(QGraphicsView::FullViewportUpdate)
        , aspectRatioMode(Qt::KeepAspectRatio)
        , rect(0.0, 0.0, 320, 240)
        , videoWidget(0)
    {
    }

    QGraphicsVideoItem *q_ptr;

    QMediaObject *mediaObject;
    QMediaService *service;
    QVideoWindowControl *windowControl;
    QPointer<QGraphicsView> currentView;
    QList<QPointer<QObject> > eventFilterTargets;
    QGraphicsView::ViewportUpdateMode savedViewportUpdateMode;

    Qt::AspectRatioMode aspectRatioMode;
    QRectF rect;
    QRectF boundingRect;
    QRectF displayRect;
    QSizeF nativeSize;

    QWidget *videoWidget;

    bool eventFilter(QObject *object, QEvent *event);
    void updateEventFilters();

    void setWidget(QWidget *widget);
    void clearService();
    void updateRects();
    void updateLastFrame();

    void _q_present();
    void _q_updateNativeSize();
    void _q_serviceDestroyed();
    void _q_mediaObjectDestroyed();
};

void QGraphicsVideoItemPrivate::_q_present()
{

}

bool QGraphicsVideoItemPrivate::eventFilter(QObject *object, QEvent *event)
{
    if (windowControl && object == videoWidget && QEvent::WinIdChange == event->type()) {
        windowControl->setWinId(videoWidget->effectiveWinId());
    } else {
        bool updateEventFiltersRequired = false;
        bool refreshDisplayRequired = false;
        foreach (QPointer<QObject> target, eventFilterTargets) {
            if (object == target.data()) {
                switch (event->type()) {
                case QEvent::ParentChange:
                    updateEventFiltersRequired = true;
                    refreshDisplayRequired = true;
                    break;
                case QEvent::Move:
                case QEvent::Resize:
                    refreshDisplayRequired = true;
                    break;
                default: ;
                }
            }
        }
        if (updateEventFiltersRequired)
            updateEventFilters();
#ifdef Q_OS_SYMBIAN
        if (refreshDisplayRequired && windowControl)
            QMetaObject::invokeMethod(windowControl, "refreshDisplay");
#endif
    }
    return false;
}

void QGraphicsVideoItemPrivate::setWidget(QWidget *widget)
{
    if (videoWidget != widget) {
        videoWidget = widget;
        if (widget) {
            windowControl->setWinId(widget->winId());
            widget->installEventFilter(this);
        }
    }
}

void QGraphicsVideoItemPrivate::clearService()
{
    if (windowControl) {
        QObject::disconnect(windowControl, SIGNAL(nativeSizeChanged()), q_ptr, SLOT(_q_updateNativeSize()));
        service->releaseControl(windowControl);
        windowControl = 0;
    }

    if (service) {
        QObject::disconnect(service, SIGNAL(destroyed()), q_ptr, SLOT(_q_serviceDestroyed()));
        service = 0;
    }
}

void QGraphicsVideoItemPrivate::updateRects()
{
    q_ptr->prepareGeometryChange();
    QSizeF videoSize;
    if (nativeSize.isEmpty()) {
        videoSize = rect.size();
    } else if (aspectRatioMode == Qt::IgnoreAspectRatio) {
        videoSize = rect.size();
    } else {
        // KeepAspectRatio or KeepAspectRatioByExpanding
        videoSize = nativeSize;
        videoSize.scale(rect.size(), aspectRatioMode);
    }
    displayRect = QRectF(QPointF(0, 0), videoSize);
    displayRect.moveCenter(rect.center());
    boundingRect = displayRect.intersected(rect);
}

void QGraphicsVideoItemPrivate::updateLastFrame()
{
}

void QGraphicsVideoItemPrivate::updateEventFilters()
{
    // In order to determine when the absolute screen position of the item
    // changes, we need to receive move events sent to m_currentView
    // or any of its ancestors.
    foreach (QPointer<QObject> target, eventFilterTargets)
        if (target)
            target->removeEventFilter(this);
    eventFilterTargets.clear();
    QObject *target = currentView;
    while (target) {
        target->installEventFilter(this);
        eventFilterTargets.append(target);
        target = target->parent();
    }
}

void QGraphicsVideoItemPrivate::_q_updateNativeSize()
{
    const QSize size = windowControl->nativeSize();
    if (nativeSize != size) {
        nativeSize = size;

        updateRects();
        emit q_ptr->nativeSizeChanged(nativeSize);
    }
}

void QGraphicsVideoItemPrivate::_q_serviceDestroyed()
{
    windowControl = 0;
    service = 0;
}

void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed()
{
    mediaObject = 0;

    clearService();
}

QGraphicsVideoItem::QGraphicsVideoItem(QGraphicsItem *parent)
    : QGraphicsObject(parent)
    , d_ptr(new QGraphicsVideoItemPrivate)
{
    d_ptr->q_ptr = this;

    setCacheMode(NoCache);
    setFlag(QGraphicsItem::ItemIgnoresParentOpacity);
    setFlag(QGraphicsItem::ItemSendsGeometryChanges);
    setFlag(QGraphicsItem::ItemSendsScenePositionChanges);
}

QGraphicsVideoItem::~QGraphicsVideoItem()
{
    if (d_ptr->windowControl) {
        d_ptr->service->releaseControl(d_ptr->windowControl);
    }

    if (d_ptr->currentView)
        d_ptr->currentView->setViewportUpdateMode(d_ptr->savedViewportUpdateMode);

    delete d_ptr;
}

QMediaObject *QGraphicsVideoItem::mediaObject() const
{
    return d_func()->mediaObject;
}

bool QGraphicsVideoItem::setMediaObject(QMediaObject *object)
{
    Q_D(QGraphicsVideoItem);

    if (object == d->mediaObject)
        return true;

    d->clearService();

    d->mediaObject = object;

    if (d->mediaObject) {
        d->service = d->mediaObject->service();

        if (d->service) {
            d->windowControl = qobject_cast<QVideoWindowControl *>(
                    d->service->requestControl(QVideoWindowControl_iid));

            if (d->windowControl != 0) {
                connect(d->service, SIGNAL(destroyed()), SLOT(_q_serviceDestroyed()));
                connect(d->windowControl, SIGNAL(nativeSizeChanged()), SLOT(_q_updateNativeSize()));
                d->windowControl->setAspectRatioMode(Qt::IgnoreAspectRatio);
                //d->windowControl->setProperty("colorKey", QVariant(QColor(16,7,2)));
                d->windowControl->setProperty("autopaintColorKey", QVariant(false));

                d->updateRects();
                return true;
            } else {
                qWarning() << "Service doesn't support QVideoWindowControl, overlay item failed";
            }
        }
    }

    d->mediaObject = 0;
    return false;
}

Qt::AspectRatioMode QGraphicsVideoItem::aspectRatioMode() const
{
    return d_func()->aspectRatioMode;
}

void QGraphicsVideoItem::setAspectRatioMode(Qt::AspectRatioMode mode)
{
    Q_D(QGraphicsVideoItem);

    d->aspectRatioMode = mode;
    d->updateRects();
}

QPointF QGraphicsVideoItem::offset() const
{
    return d_func()->rect.topLeft();
}

void QGraphicsVideoItem::setOffset(const QPointF &offset)
{
    Q_D(QGraphicsVideoItem);

    d->rect.moveTo(offset);
    d->updateRects();
}

QSizeF QGraphicsVideoItem::size() const
{
    return d_func()->rect.size();
}

void QGraphicsVideoItem::setSize(const QSizeF &size)
{
    Q_D(QGraphicsVideoItem);

    d->rect.setSize(size.isValid() ? size : QSizeF(0, 0));
    d->updateRects();
}

QSizeF QGraphicsVideoItem::nativeSize() const
{
    return d_func()->nativeSize;
}

QRectF QGraphicsVideoItem::boundingRect() const
{
    return d_func()->boundingRect;
}

void QGraphicsVideoItem::paint(
        QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
#ifdef DEBUG_GFX_VIDEO_ITEM
    qDebug() << "QGraphicsVideoItem::paint";
#endif

    Q_UNUSED(option);
    Q_D(QGraphicsVideoItem);

    QGraphicsView *view = 0;
    if (scene() && !scene()->views().isEmpty())
        view = scene()->views().first();

    //it's necessary to switch vieport update mode to FullViewportUpdate
    //otherwise the video item area can be just scrolled without notifying overlay
    //about geometry changes
    if (view != d->currentView) {
        if (d->currentView) {
            d->currentView->setViewportUpdateMode(d->savedViewportUpdateMode);
        }

        d->currentView = view;
        if (view) {
            d->savedViewportUpdateMode = view->viewportUpdateMode();
            view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
        }
        d->updateEventFilters();
    }

    QColor colorKey = Qt::black;

    if (d->windowControl != 0 && widget != 0) {
        d->setWidget(widget);

        QTransform transform = painter->combinedTransform();
        QRect overlayRect = transform.mapRect(d->displayRect).toRect();
        QRect currentSurfaceRect = d->windowControl->displayRect();

        if (currentSurfaceRect != overlayRect) {
#ifdef DEBUG_GFX_VIDEO_ITEM
            qDebug() << "set video display rect:" << overlayRect;
#endif
            d->windowControl->setDisplayRect(overlayRect);
        }

        colorKey = d->windowControl->property("colorKey").value<QColor>();
#ifdef QGRAPHICSVIDEOITEM_ROTATION_SUPPORT
        const qreal angle = transform.map(QLineF(0, 0, 1, 0)).angle();
        d->windowControl->setProperty("rotation", QVariant::fromValue<qreal>(angle));
#endif
    }

    if (colorKey.alpha() != 255)
        painter->setCompositionMode(QPainter::CompositionMode_Source);
    painter->fillRect(d->boundingRect, colorKey);
}

QVariant QGraphicsVideoItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
    Q_D(QGraphicsVideoItem);

    switch (change) {
    case ItemScenePositionHasChanged:
        update(boundingRect());
        break;
    case ItemVisibleChange:
        //move overlay out of the screen if video item becomes invisible
        if (d->windowControl != 0 && !value.toBool())
            d->windowControl->setDisplayRect(QRect(-1,-1,1,1));
        break;
    default:
        break;
    }

    return QGraphicsItem::itemChange(change, value);
}

void QGraphicsVideoItem::timerEvent(QTimerEvent *event)
{
    QGraphicsObject::timerEvent(event);
}

#include "moc_qgraphicsvideoitem.cpp"
QT_END_NAMESPACE
<|endoftext|>


<commit_before>#include <beast/core/streambuf.hpp>
#include <beast/http/read.hpp>
#include <beast/http/string_body.hpp>
#include <beast/http/write.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/program_options.hpp>
#include <iostream>
#include <silicium/sink/file_sink.hpp>
#include <silicium/sink/throwing_sink.hpp>
#include <ventura/file_operations.hpp>
#include <ventura/read_file.hpp>
#include <html_generator/tools/all.hpp>

namespace
{

	boost::system::error_code
	generate_all_html(ventura::absolute_path snippets_source_code,
	                  ventura::absolute_path const &existing_output_root,
	                  boost::string_ref const file_name)
	{
		ventura::absolute_path const index_path =
		    existing_output_root /
		    ventura::relative_path(file_name.begin(), file_name.end());
		Si::error_or<Si::file_handle> const index = ventura::overwrite_file(
		    ventura::safe_c_str(to_os_string(index_path)));
		if (index.is_error())
		{
			std::cerr << "Could not overwrite file " << index_path << '\n';
			return index.error();
		}

		Si::file_sink index_sink(index.get().handle);
		using namespace Si::html;

		static const std::string site_title = "TyRoXx' blog";

		auto page_content = dynamic([
			&file_name,
			snippets_source_code = std::move(snippets_source_code)
		](code_sink & sink)
		                            {
			                            auto drafts =
#include "pages/how-to-choose-an-integer-type.hpp"
			                                ;
			                            drafts.generate(sink);
			                        });

		auto head_content = tags::head(
		    tag("meta", attribute("charset", "utf-8"), empty) +
		    tag("meta",
		        attribute("name", "viewport") +
		            attribute("content", "width=device-width, initial-scale=1"),
		        empty) +
		    tags::title(site_title) +
		    tag("link",
		        tags::href("stylesheets.css") + attribute("rel", "stylesheet"),
		        empty));
		auto body_content =
		    tags::body(tags::h1(text(site_title)) + std::move(page_content) +
#include "pages/footer.hpp"
		               );
		auto const document =
		    raw("<!DOCTYPE html>") +
		    tags::html(std::move(head_content) + std::move(body_content));
		auto erased_sink = Si::Sink<char, Si::success>::erase(
		    Si::make_throwing_sink(index_sink));
		try
		{
			document.generate(erased_sink);
			return {};
		}
		catch (boost::system::system_error const &ex)
		{
			// TODO: do this without an exception
			return ex.code();
		}
	}

	struct file_client
	{
		boost::asio::ip::tcp::socket socket;
		beast::streambuf receive_buffer;
		beast::http::response<beast::http::string_body> response;

		explicit file_client(boost::asio::ip::tcp::socket socket,
		                     beast::streambuf receive_buffer)
		    : socket(std::move(socket))
		    , receive_buffer(std::move(receive_buffer))
		{
		}
	};

	struct http_client
	{
		boost::asio::ip::tcp::socket socket;
		beast::streambuf receive_buffer;
		beast::http::request<beast::http::string_body> request;

		explicit http_client(boost::asio::ip::tcp::socket socket,
		                     beast::streambuf receive_buffer)
		    : socket(std::move(socket))
		    , receive_buffer(std::move(receive_buffer))
		{
		}
	};

	void begin_serve(std::shared_ptr<http_client> client,
	                 ventura::absolute_path const &document_root);

	void serve_prepared_response(
	    std::shared_ptr<file_client> client, bool const is_keep_alive,
	    ventura::absolute_path const &document_root,
	    boost::optional<boost::string_ref> const content_type)
	{
		client->response.version = 11;
		client->response.fields.insert(
		    "Content-Length",
		    boost::lexical_cast<std::string>(client->response.body.size()));
		if (content_type)
		{
			client->response.fields.insert("Content-Type", *content_type);
		}
		beast::http::async_write(
		    client->socket, client->response,
		    [client, is_keep_alive,
		     document_root](boost::system::error_code const ec)
		    {
			    Si::throw_if_error(ec);
			    if (is_keep_alive)
			    {
				    auto http_client_again = std::make_shared<http_client>(
				        std::move(client->socket),
				        std::move(client->receive_buffer));
				    begin_serve(http_client_again, document_root);
			    }
			    else
			    {
				    client->socket.shutdown(
				        boost::asio::ip::tcp::socket::shutdown_both);
			    }
			});
	}

	void serve_static_file(std::shared_ptr<file_client> client,
	                       bool const is_keep_alive,
	                       ventura::absolute_path const &document_root,
	                       ventura::absolute_path const &served_document)
	{
		Si::visit<void>(
		    ventura::read_file(
		        ventura::safe_c_str(ventura::to_os_string(served_document))),
		    [&](std::vector<char> content)
		    {
			    // TODO: avoid the copy of the content
			    client->response.body.assign(content.begin(), content.end());
			    client->response.reason = "OK";
			    client->response.status = 200;
			},
		    [&](boost::system::error_code const ec)
		    {
			    std::cerr << "Could not read file " << served_document << ": "
			              << ec << '\n';
			    client->response.reason = "Internal Server Error";
			    client->response.status = 500;
			    client->response.body = client->response.reason;
			},
		    [&](ventura::read_file_problem const problem)
		    {
			    std::cerr << "Could not read file " << served_document
			              << " due to problem " << static_cast<int>(problem)
			              << '\n';
			    client->response.reason = "Internal Server Error";
			    client->response.status = 500;
			    client->response.body = client->response.reason;
			});
		serve_prepared_response(client, is_keep_alive, document_root,
		                        boost::none);
	}

	void begin_serve(std::shared_ptr<http_client> client,
	                 ventura::absolute_path const &document_root)
	{
		beast::http::async_read(
		    client->socket, client->receive_buffer, client->request,
		    [client, document_root](boost::system::error_code const ec)
		    {
			    Si::throw_if_error(ec);
			    std::shared_ptr<file_client> const new_client =
			        std::make_shared<file_client>(
			            std::move(client->socket),
			            std::move(client->receive_buffer));
			    if (!client->request.url.empty() &&
			        (client->request.url.front() == '/'))
			    {
				    boost::filesystem::path requested_file(
				        client->request.url.begin() + 1,
				        client->request.url.end());
				    if (requested_file.empty())
				    {
					    requested_file = "index.html";
				    }
				    if (requested_file.is_relative())
				    {
					    serve_static_file(
					        new_client,
					        beast::http::is_keep_alive(client->request),
					        document_root,
					        document_root / ventura::relative_path(
					                            std::move(requested_file)));
					    return;
				    }
			    }
			    new_client->response.reason = "Bad Request";
			    new_client->response.status = 400;
			    new_client->response.body = new_client->response.reason;
			    serve_prepared_response(
			        new_client, beast::http::is_keep_alive(client->request),
			        document_root, boost::string_ref("text/html"));
			});
	}

	void begin_accept(boost::asio::ip::tcp::acceptor &acceptor,
	                  ventura::absolute_path const &document_root)
	{
		auto client = std::make_shared<http_client>(
		    boost::asio::ip::tcp::socket(acceptor.get_io_service()),
		    beast::streambuf());
		acceptor.async_accept(client->socket,
		                      [&acceptor, client, document_root](
		                          boost::system::error_code const ec)
		                      {
			                      Si::throw_if_error(ec);
			                      begin_accept(acceptor, document_root);
			                      begin_serve(client, document_root);
			                  });
	}
}

int main(int argc, const char **argv)
{
	std::string output_option;
	boost::uint16_t web_server_port = 0;

	boost::program_options::options_description desc("Allowed options");
	desc.add_options()("help", "produce help message")(
	    "output", boost::program_options::value(&output_option),
	    "a directory to put the HTML files into")(
	    "serve", boost::program_options::value(&web_server_port),
	    "serve the output directory on this port");

	boost::program_options::positional_options_description positional;
	positional.add("output", 1);
	boost::program_options::variables_map vm;
	try
	{
		boost::program_options::store(
		    boost::program_options::command_line_parser(argc, argv)
		        .options(desc)
		        .positional(positional)
		        .run(),
		    vm);
	}
	catch (boost::program_options::error const &ex)
	{
		std::cerr << ex.what() << '\n' << desc << "\n";
		return 1;
	}

	boost::program_options::notify(vm);

	if (vm.count("help"))
	{
		std::cerr << desc << "\n";
		return 1;
	}

	if (output_option.empty())
	{
		std::cerr << "Please provide an absolute path to generate to.\n";
		std::cerr << desc << "\n";
		return 1;
	}

	Si::optional<ventura::absolute_path> const output_root =
	    ventura::absolute_path::create(output_option);
	if (!output_root)
	{
		std::cerr
		    << "The output directory must be given as an absolute path.\n";
		std::cerr << desc << "\n";
		return 1;
	}

	{
		boost::system::error_code const ec =
		    ventura::create_directories(*output_root, Si::return_);
		if (!!ec)
		{
			std::cerr << ec << '\n';
			return 1;
		}
	}

	ventura::absolute_path repo = *ventura::parent(
	    *ventura::parent(*ventura::absolute_path::create(__FILE__)));
	ventura::copy(
	    repo / ventura::relative_path("html_generator/pages/stylesheet.css"),
	    *output_root / ventura::relative_path("stylesheets.css"), Si::return_);
	static const boost::string_ref files_to_generate[] = {"index.html"};
	for (boost::string_ref const file : files_to_generate)
	{
		boost::system::error_code const ec = generate_all_html(
		    repo / ventura::relative_path("snippets"), *output_root, file);
		if (!!ec)
		{
			std::cerr << ec << '\n';
			return 1;
		}
	}

	if (vm.count("serve"))
	{
		try
		{
			using namespace boost::asio;

			io_service io;

			ip::tcp::acceptor acceptor_v6(
			    io, ip::tcp::endpoint(ip::tcp::v6(), web_server_port), true);
			acceptor_v6.listen();
			begin_accept(acceptor_v6, *output_root);

			ip::tcp::acceptor acceptor_v4(
			    io, ip::tcp::endpoint(ip::tcp::v4(), web_server_port), true);
			acceptor_v4.listen();
			begin_accept(acceptor_v4, *output_root);

			while (!io.stopped())
			{
				try
				{
					io.run();
				}
				catch (boost::system::system_error const &ex)
				{
					std::cerr << "boost::system::system_error: " << ex.code()
					          << '\n';
					io.reset();
				}
				catch (std::exception const &ex)
				{
					std::cerr << "std::exception: " << ex.what() << '\n';
					io.reset();
				}
			}
		}
		catch (boost::system::system_error const &ex)
		{
			std::cerr << "boost::system::system_error: " << ex.code() << '\n';
			return 1;
		}
		catch (std::exception const &ex)
		{
			std::cerr << "std::exception: " << ex.what() << '\n';
			return 1;
		}
	}
}
<commit_msg>remove IPv6 for now because my Linux does not let me bind the port<commit_after>#include <beast/core/streambuf.hpp>
#include <beast/http/read.hpp>
#include <beast/http/string_body.hpp>
#include <beast/http/write.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/program_options.hpp>
#include <iostream>
#include <silicium/sink/file_sink.hpp>
#include <silicium/sink/throwing_sink.hpp>
#include <ventura/file_operations.hpp>
#include <ventura/read_file.hpp>
#include <html_generator/tools/all.hpp>

namespace
{

	boost::system::error_code
	generate_all_html(ventura::absolute_path snippets_source_code,
	                  ventura::absolute_path const &existing_output_root,
	                  boost::string_ref const file_name)
	{
		ventura::absolute_path const index_path =
		    existing_output_root /
		    ventura::relative_path(file_name.begin(), file_name.end());
		Si::error_or<Si::file_handle> const index = ventura::overwrite_file(
		    ventura::safe_c_str(to_os_string(index_path)));
		if (index.is_error())
		{
			std::cerr << "Could not overwrite file " << index_path << '\n';
			return index.error();
		}

		Si::file_sink index_sink(index.get().handle);
		using namespace Si::html;

		static const std::string site_title = "TyRoXx' blog";

		auto page_content = dynamic([
			&file_name,
			snippets_source_code = std::move(snippets_source_code)
		](code_sink & sink)
		                            {
			                            auto drafts =
#include "pages/how-to-choose-an-integer-type.hpp"
			                                ;
			                            drafts.generate(sink);
			                        });

		auto head_content = tags::head(
		    tag("meta", attribute("charset", "utf-8"), empty) +
		    tag("meta",
		        attribute("name", "viewport") +
		            attribute("content", "width=device-width, initial-scale=1"),
		        empty) +
		    tags::title(site_title) +
		    tag("link",
		        tags::href("stylesheets.css") + attribute("rel", "stylesheet"),
		        empty));
		auto body_content =
		    tags::body(tags::h1(text(site_title)) + std::move(page_content) +
#include "pages/footer.hpp"
		               );
		auto const document =
		    raw("<!DOCTYPE html>") +
		    tags::html(std::move(head_content) + std::move(body_content));
		auto erased_sink = Si::Sink<char, Si::success>::erase(
		    Si::make_throwing_sink(index_sink));
		try
		{
			document.generate(erased_sink);
			return {};
		}
		catch (boost::system::system_error const &ex)
		{
			// TODO: do this without an exception
			return ex.code();
		}
	}

	struct file_client
	{
		boost::asio::ip::tcp::socket socket;
		beast::streambuf receive_buffer;
		beast::http::response<beast::http::string_body> response;

		explicit file_client(boost::asio::ip::tcp::socket socket,
		                     beast::streambuf receive_buffer)
		    : socket(std::move(socket))
		    , receive_buffer(std::move(receive_buffer))
		{
		}
	};

	struct http_client
	{
		boost::asio::ip::tcp::socket socket;
		beast::streambuf receive_buffer;
		beast::http::request<beast::http::string_body> request;

		explicit http_client(boost::asio::ip::tcp::socket socket,
		                     beast::streambuf receive_buffer)
		    : socket(std::move(socket))
		    , receive_buffer(std::move(receive_buffer))
		{
		}
	};

	void begin_serve(std::shared_ptr<http_client> client,
	                 ventura::absolute_path const &document_root);

	void serve_prepared_response(
	    std::shared_ptr<file_client> client, bool const is_keep_alive,
	    ventura::absolute_path const &document_root,
	    boost::optional<boost::string_ref> const content_type)
	{
		client->response.version = 11;
		client->response.fields.insert(
		    "Content-Length",
		    boost::lexical_cast<std::string>(client->response.body.size()));
		if (content_type)
		{
			client->response.fields.insert("Content-Type", *content_type);
		}
		beast::http::async_write(
		    client->socket, client->response,
		    [client, is_keep_alive,
		     document_root](boost::system::error_code const ec)
		    {
			    Si::throw_if_error(ec);
			    if (is_keep_alive)
			    {
				    auto http_client_again = std::make_shared<http_client>(
				        std::move(client->socket),
				        std::move(client->receive_buffer));
				    begin_serve(http_client_again, document_root);
			    }
			    else
			    {
				    client->socket.shutdown(
				        boost::asio::ip::tcp::socket::shutdown_both);
			    }
			});
	}

	void serve_static_file(std::shared_ptr<file_client> client,
	                       bool const is_keep_alive,
	                       ventura::absolute_path const &document_root,
	                       ventura::absolute_path const &served_document)
	{
		Si::visit<void>(
		    ventura::read_file(
		        ventura::safe_c_str(ventura::to_os_string(served_document))),
		    [&](std::vector<char> content)
		    {
			    // TODO: avoid the copy of the content
			    client->response.body.assign(content.begin(), content.end());
			    client->response.reason = "OK";
			    client->response.status = 200;
			},
		    [&](boost::system::error_code const ec)
		    {
			    std::cerr << "Could not read file " << served_document << ": "
			              << ec << '\n';
			    client->response.reason = "Internal Server Error";
			    client->response.status = 500;
			    client->response.body = client->response.reason;
			},
		    [&](ventura::read_file_problem const problem)
		    {
			    std::cerr << "Could not read file " << served_document
			              << " due to problem " << static_cast<int>(problem)
			              << '\n';
			    client->response.reason = "Internal Server Error";
			    client->response.status = 500;
			    client->response.body = client->response.reason;
			});
		serve_prepared_response(client, is_keep_alive, document_root,
		                        boost::none);
	}

	void begin_serve(std::shared_ptr<http_client> client,
	                 ventura::absolute_path const &document_root)
	{
		beast::http::async_read(
		    client->socket, client->receive_buffer, client->request,
		    [client, document_root](boost::system::error_code const ec)
		    {
			    Si::throw_if_error(ec);
			    std::shared_ptr<file_client> const new_client =
			        std::make_shared<file_client>(
			            std::move(client->socket),
			            std::move(client->receive_buffer));
			    if (!client->request.url.empty() &&
			        (client->request.url.front() == '/'))
			    {
				    boost::filesystem::path requested_file(
				        client->request.url.begin() + 1,
				        client->request.url.end());
				    if (requested_file.empty())
				    {
					    requested_file = "index.html";
				    }
				    if (requested_file.is_relative())
				    {
					    serve_static_file(
					        new_client,
					        beast::http::is_keep_alive(client->request),
					        document_root,
					        document_root / ventura::relative_path(
					                            std::move(requested_file)));
					    return;
				    }
			    }
			    new_client->response.reason = "Bad Request";
			    new_client->response.status = 400;
			    new_client->response.body = new_client->response.reason;
			    serve_prepared_response(
			        new_client, beast::http::is_keep_alive(client->request),
			        document_root, boost::string_ref("text/html"));
			});
	}

	void begin_accept(boost::asio::ip::tcp::acceptor &acceptor,
	                  ventura::absolute_path const &document_root)
	{
		auto client = std::make_shared<http_client>(
		    boost::asio::ip::tcp::socket(acceptor.get_io_service()),
		    beast::streambuf());
		acceptor.async_accept(client->socket,
		                      [&acceptor, client, document_root](
		                          boost::system::error_code const ec)
		                      {
			                      Si::throw_if_error(ec);
			                      begin_accept(acceptor, document_root);
			                      begin_serve(client, document_root);
			                  });
	}
}

int main(int argc, const char **argv)
{
	std::string output_option;
	boost::uint16_t web_server_port = 0;

	boost::program_options::options_description desc("Allowed options");
	desc.add_options()("help", "produce help message")(
	    "output", boost::program_options::value(&output_option),
	    "a directory to put the HTML files into")(
	    "serve", boost::program_options::value(&web_server_port),
	    "serve the output directory on this port");

	boost::program_options::positional_options_description positional;
	positional.add("output", 1);
	boost::program_options::variables_map vm;
	try
	{
		boost::program_options::store(
		    boost::program_options::command_line_parser(argc, argv)
		        .options(desc)
		        .positional(positional)
		        .run(),
		    vm);
	}
	catch (boost::program_options::error const &ex)
	{
		std::cerr << ex.what() << '\n' << desc << "\n";
		return 1;
	}

	boost::program_options::notify(vm);

	if (vm.count("help"))
	{
		std::cerr << desc << "\n";
		return 1;
	}

	if (output_option.empty())
	{
		std::cerr << "Please provide an absolute path to generate to.\n";
		std::cerr << desc << "\n";
		return 1;
	}

	Si::optional<ventura::absolute_path> const output_root =
	    ventura::absolute_path::create(output_option);
	if (!output_root)
	{
		std::cerr
		    << "The output directory must be given as an absolute path.\n";
		std::cerr << desc << "\n";
		return 1;
	}

	{
		boost::system::error_code const ec =
		    ventura::create_directories(*output_root, Si::return_);
		if (!!ec)
		{
			std::cerr << ec << '\n';
			return 1;
		}
	}

	ventura::absolute_path repo = *ventura::parent(
	    *ventura::parent(*ventura::absolute_path::create(__FILE__)));
	ventura::copy(
	    repo / ventura::relative_path("html_generator/pages/stylesheet.css"),
	    *output_root / ventura::relative_path("stylesheets.css"), Si::return_);
	static const boost::string_ref files_to_generate[] = {"index.html"};
	for (boost::string_ref const file : files_to_generate)
	{
		boost::system::error_code const ec = generate_all_html(
		    repo / ventura::relative_path("snippets"), *output_root, file);
		if (!!ec)
		{
			std::cerr << ec << '\n';
			return 1;
		}
	}

	if (vm.count("serve"))
	{
		try
		{
			using namespace boost::asio;

			io_service io;

			ip::tcp::acceptor acceptor_v4(
			    io, ip::tcp::endpoint(ip::tcp::v4(), web_server_port), true);
			acceptor_v4.listen();
			begin_accept(acceptor_v4, *output_root);

			while (!io.stopped())
			{
				try
				{
					io.run();
				}
				catch (boost::system::system_error const &ex)
				{
					std::cerr << "boost::system::system_error: " << ex.code()
					          << '\n';
					io.reset();
				}
				catch (std::exception const &ex)
				{
					std::cerr << "std::exception: " << ex.what() << '\n';
					io.reset();
				}
			}
		}
		catch (boost::system::system_error const &ex)
		{
			std::cerr << "boost::system::system_error: " << ex.code() << '\n';
			return 1;
		}
		catch (std::exception const &ex)
		{
			std::cerr << "std::exception: " << ex.what() << '\n';
			return 1;
		}
	}
}
<|endoftext|>