<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Standard ValueList Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include <predicate/standard_valuelist.hpp>

#include <predicate/call_factory.hpp>
#include <predicate/call_helpers.hpp>
#include <predicate/validate.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {
namespace Standard {

namespace {

static const node_p c_false(new Null());

}

string SetName::name() const
{
    return "setName";
}

Value SetName::value_calculate(Value v, EvalContext context)
{
    Value name = literal_value(children().front());
    ConstByteString name_bs = name.value_as_byte_string();

    return v.dup(v.memory_pool(), name_bs.const_data(), name_bs.length());
}

void SetName::calculate(EvalContext context)
{
    map_calculate(children().back(), context);
}

bool SetName::validate(NodeReporter reporter) const
{
    return
        Validate::n_children(reporter, 2) &&
        Validate::nth_child_is_string(reporter, 0) &&
        Validate::nth_child_is_not_null(reporter, 1)
        ;
}

string Cat::name() const
{
    return "cat";
}

bool Cat::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();
    bool result = false;

    // Remove null children.
    {
        node_list_t to_remove;
        BOOST_FOREACH(const node_p& child, children()) {
            if (child->is_literal() && ! literal_value(child)) {
                to_remove.push_back(child);
            }
        }
        BOOST_FOREACH(const node_p& child, to_remove) {
            merge_graph.remove(me, child);
        }

        result = true;
    }

    // Become child if only one child.
    if (children().size() == 1) {
        node_p replacement = children().front();
        merge_graph.replace(me, replacement);
        return true;
    }

    // Become false if no children.
    if (children().size() == 0) {
        node_p replacement = c_false;
        merge_graph.replace(me, replacement);
        return true;
    }

    return result;
}

void Cat::calculate(EvalContext context)
{
    // @todo Change to be opportunistic.  I.e., add values of first
    // child immediately.  Once that child is finished, do same for next,
    // and so on.

    // Do nothing if any unfinished children.
    BOOST_FOREACH(const node_p& child, children()) {
        child->eval(context);
        if (! child->is_finished()) {
            return;
        }
    }

    // All children finished, concatenate values.
    BOOST_FOREACH(const node_p& child, children()) {
        BOOST_FOREACH(Value v, child->values()) {
            add_value(v);
        }
    }
    finish();
}

string First::name() const
{
    return "first";
}

void First::calculate(EvalContext context)
{
    const node_p& child = children().front();
    ValueList values = child->eval(context);
    if (! values.empty()) {
        add_value(values.front());
        finish();
    }
    else if (child->is_finished()) {
        finish();
    }
}

bool First::validate(NodeReporter reporter) const
{
    return Validate::n_children(reporter, 1);
}

struct Rest::data_t
{
    boost::thread_specific_ptr<ValueList::const_iterator> location;
};

Rest::Rest() :
    m_data(new data_t())
{
    // nop
}

string Rest::name() const
{
    return "rest";
}

void Rest::reset()
{
    if (m_data->location.get()) {
        *(m_data->location) = ValueList::const_iterator();
    }
    else {
        m_data->location.reset(new ValueList::const_iterator());
    }
}

void Rest::calculate(EvalContext context)
{
    const node_p& child = children().front();
    ValueList values = child->eval(context);
    ValueList::const_iterator& location = *(m_data->location.get());

    // Special case if no values yet.
    if (values.empty()) {
        if (child->is_finished()) {
            finish();
        }
        return;
    }

    if (location == ValueList::const_iterator()) {
        location = values.begin();
    }

    // At this point, location refers to element before next one
    // to push.
    ValueList::const_iterator next_location = location;
    ++next_location;
    const ValueList::const_iterator end = values.end();
    while (next_location != end) {
        add_value(*next_location);
        location = next_location;
        ++next_location;
    }

    if (child->is_finished()) {
        finish();
    }
}

bool Rest::validate(NodeReporter reporter) const
{
    return Validate::n_children(reporter, 1);
}

string Nth::name() const
{
    return "nth";
}

void Nth::calculate(EvalContext context)
{
    int64_t n = literal_value(children().front()).value_as_number();

    if (n <= 0) {
        finish();
        return;
    }

    const node_p& child = children().back();
    ValueList values = child->eval(context);

    if (values.size() < size_t(n)) {
        if (child->is_finished()) {
            finish();
        }
        return;
    }

    ValueList::const_iterator i = values.begin();
    advance(i, n - 1);

    add_value(*i);
    finish();
}

bool Nth::validate(NodeReporter reporter) const
{
    return
        Validate::n_children(reporter, 2) &&
        Validate::nth_child_is_integer_above(reporter, 0, -1)
        ;
}

string Scatter::name() const
{
    return "scatter";
}

void Scatter::calculate(EvalContext context)
{
    const node_p& child = children().front();
    child->eval(context);

    if (! child->is_finished()) {
        return;
    }

    Value value = simple_value(child);
    if (value) {
        BOOST_FOREACH(Value v, value.value_as_list<Value>()) {
            add_value(v);
        }
        finish();
    }
}

bool Scatter::validate(NodeReporter reporter) const
{
    return Validate::n_children(reporter, 1);
}

string Gather::name() const
{
    return "gather";
}

void Gather::calculate(EvalContext context)
{
    const node_p& child = children().front();
    child->eval(context);

    if (! child->is_finished()) {
        return;
    }

    List<Value> values =
        List<Value>::create(context.memory_pool());

    copy(
        child->values().begin(), child->values().end(),
        back_inserter(values)
    );

    add_value(Field::create_no_copy_list(
        context.memory_pool(),
        "", 0,
        values
    ));

    finish();
}

bool Gather::validate(NodeReporter reporter) const
{
    return Validate::n_children(reporter, 1);
}

void load_valuelist(CallFactory& to)
{
    to
        .add<SetName>()
        .add<Cat>()
        .add<First>()
        .add<Rest>()
        .add<Nth>()
        .add<Scatter>()
        .add<Gather>()
        ;
}

} // Standard
} // Predicate
} // IronBee
<commit_msg>predicate/standard_valuelist: Fix bug in cat transformations.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Standard ValueList Implementation
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#include <predicate/standard_valuelist.hpp>

#include <predicate/call_factory.hpp>
#include <predicate/call_helpers.hpp>
#include <predicate/validate.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {
namespace Standard {

namespace {

static const node_p c_false(new Null());

}

string SetName::name() const
{
    return "setName";
}

Value SetName::value_calculate(Value v, EvalContext context)
{
    Value name = literal_value(children().front());
    ConstByteString name_bs = name.value_as_byte_string();

    return v.dup(v.memory_pool(), name_bs.const_data(), name_bs.length());
}

void SetName::calculate(EvalContext context)
{
    map_calculate(children().back(), context);
}

bool SetName::validate(NodeReporter reporter) const
{
    return
        Validate::n_children(reporter, 2) &&
        Validate::nth_child_is_string(reporter, 0) &&
        Validate::nth_child_is_not_null(reporter, 1)
        ;
}

string Cat::name() const
{
    return "cat";
}

bool Cat::transform(
    MergeGraph&        merge_graph,
    const CallFactory& call_factory,
    NodeReporter       reporter
)
{
    node_p me = shared_from_this();
    bool result = false;

    // Remove null children.
    {
        node_list_t to_remove;
        BOOST_FOREACH(const node_p& child, children()) {
            if (child->is_literal() && ! literal_value(child)) {
                to_remove.push_back(child);
            }
        }
        BOOST_FOREACH(const node_p& child, to_remove) {
            merge_graph.remove(me, child);
        }

        if (! to_remove.empty()) {
            result = true;
        }
    }

    // Become child if only one child.
    if (children().size() == 1) {
        node_p replacement = children().front();
        merge_graph.replace(me, replacement);
        return true;
    }

    // Become false if no children.
    if (children().size() == 0) {
        node_p replacement = c_false;
        merge_graph.replace(me, replacement);
        return true;
    }

    return result;
}

void Cat::calculate(EvalContext context)
{
    // @todo Change to be opportunistic.  I.e., add values of first
    // child immediately.  Once that child is finished, do same for next,
    // and so on.

    // Do nothing if any unfinished children.
    BOOST_FOREACH(const node_p& child, children()) {
        child->eval(context);
        if (! child->is_finished()) {
            return;
        }
    }

    // All children finished, concatenate values.
    BOOST_FOREACH(const node_p& child, children()) {
        BOOST_FOREACH(Value v, child->values()) {
            add_value(v);
        }
    }
    finish();
}

string First::name() const
{
    return "first";
}

void First::calculate(EvalContext context)
{
    const node_p& child = children().front();
    ValueList values = child->eval(context);
    if (! values.empty()) {
        add_value(values.front());
        finish();
    }
    else if (child->is_finished()) {
        finish();
    }
}

bool First::validate(NodeReporter reporter) const
{
    return Validate::n_children(reporter, 1);
}

struct Rest::data_t
{
    boost::thread_specific_ptr<ValueList::const_iterator> location;
};

Rest::Rest() :
    m_data(new data_t())
{
    // nop
}

string Rest::name() const
{
    return "rest";
}

void Rest::reset()
{
    if (m_data->location.get()) {
        *(m_data->location) = ValueList::const_iterator();
    }
    else {
        m_data->location.reset(new ValueList::const_iterator());
    }
}

void Rest::calculate(EvalContext context)
{
    const node_p& child = children().front();
    ValueList values = child->eval(context);
    ValueList::const_iterator& location = *(m_data->location.get());

    // Special case if no values yet.
    if (values.empty()) {
        if (child->is_finished()) {
            finish();
        }
        return;
    }

    if (location == ValueList::const_iterator()) {
        location = values.begin();
    }

    // At this point, location refers to element before next one
    // to push.
    ValueList::const_iterator next_location = location;
    ++next_location;
    const ValueList::const_iterator end = values.end();
    while (next_location != end) {
        add_value(*next_location);
        location = next_location;
        ++next_location;
    }

    if (child->is_finished()) {
        finish();
    }
}

bool Rest::validate(NodeReporter reporter) const
{
    return Validate::n_children(reporter, 1);
}

string Nth::name() const
{
    return "nth";
}

void Nth::calculate(EvalContext context)
{
    int64_t n = literal_value(children().front()).value_as_number();

    if (n <= 0) {
        finish();
        return;
    }

    const node_p& child = children().back();
    ValueList values = child->eval(context);

    if (values.size() < size_t(n)) {
        if (child->is_finished()) {
            finish();
        }
        return;
    }

    ValueList::const_iterator i = values.begin();
    advance(i, n - 1);

    add_value(*i);
    finish();
}

bool Nth::validate(NodeReporter reporter) const
{
    return
        Validate::n_children(reporter, 2) &&
        Validate::nth_child_is_integer_above(reporter, 0, -1)
        ;
}

string Scatter::name() const
{
    return "scatter";
}

void Scatter::calculate(EvalContext context)
{
    const node_p& child = children().front();
    child->eval(context);

    if (! child->is_finished()) {
        return;
    }

    Value value = simple_value(child);
    if (value) {
        BOOST_FOREACH(Value v, value.value_as_list<Value>()) {
            add_value(v);
        }
        finish();
    }
}

bool Scatter::validate(NodeReporter reporter) const
{
    return Validate::n_children(reporter, 1);
}

string Gather::name() const
{
    return "gather";
}

void Gather::calculate(EvalContext context)
{
    const node_p& child = children().front();
    child->eval(context);

    if (! child->is_finished()) {
        return;
    }

    List<Value> values =
        List<Value>::create(context.memory_pool());

    copy(
        child->values().begin(), child->values().end(),
        back_inserter(values)
    );

    add_value(Field::create_no_copy_list(
        context.memory_pool(),
        "", 0,
        values
    ));

    finish();
}

bool Gather::validate(NodeReporter reporter) const
{
    return Validate::n_children(reporter, 1);
}

void load_valuelist(CallFactory& to)
{
    to
        .add<SetName>()
        .add<Cat>()
        .add<First>()
        .add<Rest>()
        .add<Nth>()
        .add<Scatter>()
        .add<Gather>()
        ;
}

} // Standard
} // Predicate
} // IronBee
<|endoftext|>


<commit_before>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Standard ValueList.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __PREDICATE__STANDARD_VALUELIST__
#define __PREDICATE__STANDARD_VALUELIST__

#include <predicate/standard_valuelist.hpp>

#include <predicate/merge_graph.hpp>

#include <ironbeepp/operator.hpp>
#include <ironbeepp/transformation.hpp>
#include <predicate/meta_call.hpp>
#include <predicate/validate.hpp>

#include <boost/foreach.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {
namespace Standard {

/**
 * Construct a named value from a name (string) and value.
 **/
class SetName :
    public MaplikeCall,
    public Validate::Call<SetName>,
    public Validate::NChildren<2,
           Validate::NthChildIsString<0,
           Validate::NthChildIsNotNull<1
           > > >
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual Value value_calculate(Value v, EvalContext context);
    virtual void calculate(EvalContext context);
};

/**
 * Concatenate values of children.
 **/
class Cat :
    public Call
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * First value.
 **/
class First :
    public Validate::Call<First>,
    public Validate::NChildren<1>
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * All but first value.
 **/
class Rest :
    public Validate::Call<Rest>,
    public Validate::NChildren<1>
{
public:
    //! Constructor.
    Rest();

    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void reset();
    virtual void calculate(EvalContext context);

private:
    //! Hidden complex implementation details.
    struct data_t;

    //! Hidden complex implementation details.
    boost::scoped_ptr<data_t> m_data;
};

/**
 * Nth value.
 **/
class Nth :
    public Validate::Call<Nth>,
    public Validate::NChildren<2,
           Validate::NthChildIsInteger<0
           > >
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * Expand simple list value.
 **/
class Scatter :
    public Validate::Call<Scatter>,
    public Validate::NChildren<1>
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * Gathers values into simple list value.
 **/
class Gather :
    public Validate::Call<Gather>,
    public Validate::NChildren<1>
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * Load all standard valielist calls into a CallFactory.
 *
 * @param [in] to CallFactory to load into.
 **/
void load_valuelist(CallFactory& to);

} // Standard
} // Predicate
} // IronBee

#endif
<commit_msg>predicate/standard_valuelist: Cleanup.<commit_after>/*****************************************************************************
 * Licensed to Qualys, Inc. (QUALYS) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * QUALYS licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ****************************************************************************/

/**
 * @file
 * @brief Predicate --- Standard ValueList.
 *
 * @author Christopher Alfeld <calfeld@qualys.com>
 */

#ifndef __PREDICATE__STANDARD_VALUELIST__
#define __PREDICATE__STANDARD_VALUELIST__

#include <predicate/merge_graph.hpp>

#include <ironbeepp/operator.hpp>
#include <ironbeepp/transformation.hpp>
#include <predicate/meta_call.hpp>
#include <predicate/validate.hpp>

#include <boost/foreach.hpp>

using namespace std;

namespace IronBee {
namespace Predicate {
namespace Standard {

/**
 * Construct a named value from a name (string) and value.
 **/
class SetName :
    public MaplikeCall,
    public Validate::Call<SetName>,
    public Validate::NChildren<2,
           Validate::NthChildIsString<0,
           Validate::NthChildIsNotNull<1
           > > >
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual Value value_calculate(Value v, EvalContext context);
    virtual void calculate(EvalContext context);
};

/**
 * Concatenate values of children.
 **/
class Cat :
    public Call
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * First value.
 **/
class First :
    public Validate::Call<First>,
    public Validate::NChildren<1>
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * All but first value.
 **/
class Rest :
    public Validate::Call<Rest>,
    public Validate::NChildren<1>
{
public:
    //! Constructor.
    Rest();

    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void reset();
    virtual void calculate(EvalContext context);

private:
    //! Hidden complex implementation details.
    struct data_t;

    //! Hidden complex implementation details.
    boost::scoped_ptr<data_t> m_data;
};

/**
 * Nth value.
 **/
class Nth :
    public Validate::Call<Nth>,
    public Validate::NChildren<2,
           Validate::NthChildIsInteger<0
           > >
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * Expand simple list value.
 **/
class Scatter :
    public Validate::Call<Scatter>,
    public Validate::NChildren<1>
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * Gathers values into simple list value.
 **/
class Gather :
    public Validate::Call<Gather>,
    public Validate::NChildren<1>
{
public:
    //! See Call:name()
    virtual std::string name() const;

protected:
    virtual void calculate(EvalContext context);
};

/**
 * Load all standard valuelists calls into a CallFactory.
 *
 * @param [in] to CallFactory to load into.
 **/
void load_valuelist(CallFactory& to);

} // Standard
} // Predicate
} // IronBee

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: EventThread.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: fs $ $Date: 2001-08-22 13:57:07 $
 *
 *  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 _FRM_EVENT_THREAD_HXX_
#define _FRM_EVENT_THREAD_HXX_

#include <com/sun/star/lang/XEventListener.hpp>
#include <com/sun/star/lang/EventObject.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/awt/XControl.hpp>
#include <vos/thread.hxx>

#ifndef _OSL_CONDITN_HXX_
#include <osl/conditn.hxx>
#endif
#ifndef _CPPUHELPER_COMPONENT_HXX_
#include <cppuhelper/component.hxx>
#endif

#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COMPHELPER_GUARDING_HXX_
#include <comphelper/guarding.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
using namespace comphelper;

//.........................................................................
namespace frm
{
//.........................................................................

// ***************************************************************************************************
// ***************************************************************************************************

typedef ::vos::OThread  OComponentEventThread_TBASE;
class OComponentEventThread
            :public OComponentEventThread_TBASE
            ,public ::com::sun::star::lang::XEventListener
            ,public ::cppu::OWeakObject
{
    DECLARE_STL_VECTOR(::com::sun::star::lang::EventObject*, ThreadEvents);
    DECLARE_STL_VECTOR(::com::sun::star::uno::Reference< ::com::sun::star::uno::XAdapter> , ThreadObjects);
    DECLARE_STL_VECTOR(sal_Bool,    ThreadBools);

    OCountedMutex                   m_aMutex;
    ::osl::Condition                m_aCond;            // Queue gefuellt?
    ThreadEvents                    m_aEvents;          // Event-Queue
    ThreadObjects                   m_aControls;        // Control fuer Submit
    ThreadBools                     m_aFlags;           // Flags fuer Submit/Reset

    ::cppu::OComponentHelper*                   m_pCompImpl;    // Implementierung des Controls
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent>   m_xComp;        // ::com::sun::star::lang::XComponent des Controls

protected:

    // XThread
    virtual void SAL_CALL run();

    virtual void SAL_CALL kill();
    virtual void SAL_CALL onTerminated();

    // Die folgende Methode wird gerufen um das Event unter Beruecksichtigung
    // seines Typs zu duplizieren.
    virtual ::com::sun::star::lang::EventObject* cloneEvent(const ::com::sun::star::lang::EventObject* _pEvt) const = 0;

    // Ein Event bearbeiten. Der Mutex ist dabei nicht gelockt, pCompImpl
    // bleibt aber in jedem Fall gueltig. Bei pEvt kann es sich auch um
    // einen abgeleiteten Typ handeln, naemlich den, den cloneEvent
    // zurueckgibt. rControl ist nur gesetzt, wenn beim addEvent ein
    // Control uebergeben wurde. Da das Control nur als WeakRef gehalten
    // wird kann es auch zwischenzeitlich verschwinden.
    virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl,
                               const ::com::sun::star::lang::EventObject* _pEvt,
                               const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& _rControl,
                               sal_Bool _bFlag) = 0;

public:

    // UNO Anbindung
    DECLARE_UNO3_DEFAULTS(OComponentEventThread, OWeakObject);
    virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type& _rType) throw (::com::sun::star::uno::RuntimeException);

    OComponentEventThread(::cppu::OComponentHelper* pCompImpl);
    virtual ~OComponentEventThread();

    void addEvent( const ::com::sun::star::lang::EventObject* _pEvt, sal_Bool bFlag = sal_False );
    void addEvent( const ::com::sun::star::lang::EventObject* _pEvt, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& rControl,
                   sal_Bool bFlag = sal_False );

    // ::com::sun::star::lang::XEventListener
    virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource );

/* resolve ambiguity : both OWeakObject and OObject have these memory operators */
    void * SAL_CALL operator new( size_t size ) throw() { return OThread::operator new(size); }
    void SAL_CALL operator delete( void * p ) throw() { OThread::operator delete(p); }

private:
    void    implStarted( );
    void    implTerminated( );
};

//.........................................................................
}   // namespace frm
//.........................................................................

#endif // _FRM_EVENT_THREAD_HXX_

<commit_msg>#92075# exception specification<commit_after>/*************************************************************************
 *
 *  $RCSfile: EventThread.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2001-09-12 10:25:07 $
 *
 *  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 _FRM_EVENT_THREAD_HXX_
#define _FRM_EVENT_THREAD_HXX_

#include <com/sun/star/lang/XEventListener.hpp>
#include <com/sun/star/lang/EventObject.hpp>
#include <com/sun/star/lang/XComponent.hpp>
#include <com/sun/star/awt/XControl.hpp>
#include <vos/thread.hxx>

#ifndef _OSL_CONDITN_HXX_
#include <osl/conditn.hxx>
#endif
#ifndef _CPPUHELPER_COMPONENT_HXX_
#include <cppuhelper/component.hxx>
#endif

#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COMPHELPER_GUARDING_HXX_
#include <comphelper/guarding.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
using namespace comphelper;

//.........................................................................
namespace frm
{
//.........................................................................

// ***************************************************************************************************
// ***************************************************************************************************

typedef ::vos::OThread  OComponentEventThread_TBASE;
class OComponentEventThread
            :public OComponentEventThread_TBASE
            ,public ::com::sun::star::lang::XEventListener
            ,public ::cppu::OWeakObject
{
    DECLARE_STL_VECTOR(::com::sun::star::lang::EventObject*, ThreadEvents);
    DECLARE_STL_VECTOR(::com::sun::star::uno::Reference< ::com::sun::star::uno::XAdapter> , ThreadObjects);
    DECLARE_STL_VECTOR(sal_Bool,    ThreadBools);

    OCountedMutex                   m_aMutex;
    ::osl::Condition                m_aCond;            // Queue gefuellt?
    ThreadEvents                    m_aEvents;          // Event-Queue
    ThreadObjects                   m_aControls;        // Control fuer Submit
    ThreadBools                     m_aFlags;           // Flags fuer Submit/Reset

    ::cppu::OComponentHelper*                   m_pCompImpl;    // Implementierung des Controls
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent>   m_xComp;        // ::com::sun::star::lang::XComponent des Controls

protected:

    // XThread
    virtual void SAL_CALL run();

    virtual void SAL_CALL kill();
    virtual void SAL_CALL onTerminated();

    // Die folgende Methode wird gerufen um das Event unter Beruecksichtigung
    // seines Typs zu duplizieren.
    virtual ::com::sun::star::lang::EventObject* cloneEvent(const ::com::sun::star::lang::EventObject* _pEvt) const = 0;

    // Ein Event bearbeiten. Der Mutex ist dabei nicht gelockt, pCompImpl
    // bleibt aber in jedem Fall gueltig. Bei pEvt kann es sich auch um
    // einen abgeleiteten Typ handeln, naemlich den, den cloneEvent
    // zurueckgibt. rControl ist nur gesetzt, wenn beim addEvent ein
    // Control uebergeben wurde. Da das Control nur als WeakRef gehalten
    // wird kann es auch zwischenzeitlich verschwinden.
    virtual void processEvent( ::cppu::OComponentHelper* _pCompImpl,
                               const ::com::sun::star::lang::EventObject* _pEvt,
                               const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& _rControl,
                               sal_Bool _bFlag) = 0;

public:

    // UNO Anbindung
    DECLARE_UNO3_DEFAULTS(OComponentEventThread, OWeakObject);
    virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type& _rType) throw (::com::sun::star::uno::RuntimeException);

    OComponentEventThread(::cppu::OComponentHelper* pCompImpl);
    virtual ~OComponentEventThread();

    void addEvent( const ::com::sun::star::lang::EventObject* _pEvt, sal_Bool bFlag = sal_False );
    void addEvent( const ::com::sun::star::lang::EventObject* _pEvt, const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControl>& rControl,
                   sal_Bool bFlag = sal_False );

    // ::com::sun::star::lang::XEventListener
    virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource ) throw (::com::sun::star::uno::RuntimeException);

/* resolve ambiguity : both OWeakObject and OObject have these memory operators */
    void * SAL_CALL operator new( size_t size ) throw() { return OThread::operator new(size); }
    void SAL_CALL operator delete( void * p ) throw() { OThread::operator delete(p); }

private:
    void    implStarted( );
    void    implTerminated( );
};

//.........................................................................
}   // namespace frm
//.........................................................................

#endif // _FRM_EVENT_THREAD_HXX_

<|endoftext|>


<commit_before>#include "Flow.hpp"
#include <cmath>
#include <assert.h>

namespace Slic3r {

/* This constructor builds a Flow object from an extrusion width config setting
   and other context properties. */
Flow
Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio) {
    // we need layer height unless it's a bridge
    if (height <= 0 && bridge_flow_ratio == 0) CONFESS("Invalid flow height supplied to new_from_config_width()");

    float w;
    if (bridge_flow_ratio > 0) {
        // if bridge flow was requested, calculate bridge width
        height = w = Flow::_bridge_width(nozzle_diameter, bridge_flow_ratio);
    } else if (!width.percent && width.value == 0) {
        // if user left option to 0, calculate a sane default width
        w = Flow::_auto_width(role, nozzle_diameter, height);
    } else {
        // if user set a manual value, use it
        w = width.get_abs_value(height);
    }

    return Flow(w, height, nozzle_diameter, bridge_flow_ratio > 0);
}

/* This constructor builds a Flow object from a given centerline spacing. */
Flow
Flow::new_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge) {
    // we need layer height unless it's a bridge
    if (height <= 0 && !bridge) CONFESS("Invalid flow height supplied to new_from_spacing()");

    float w = Flow::_width_from_spacing(spacing, nozzle_diameter, height, bridge);
    if (bridge) height = w;
    return Flow(w, height, nozzle_diameter, bridge);
}

/* This method returns the centerline spacing between two adjacent extrusions
   having the same extrusion width (and other properties). */
float
Flow::spacing() const {
    if (this->bridge) {
        return this->width + BRIDGE_EXTRA_SPACING;
    }

    // rectangle with semicircles at the ends
    float min_flow_spacing = this->width - this->height * (1 - PI/4.0);
    return this->width - OVERLAP_FACTOR * (this->width - min_flow_spacing);
}

void
Flow::set_spacing(float spacing) {
    this->width = Flow::_width_from_spacing(spacing, this->nozzle_diameter, this->height, this->bridge);
}

/* This method returns the centerline spacing between an extrusion using this
   flow and another one using another flow.
   this->spacing(other) shall return the same value as other.spacing(*this) */
float
Flow::spacing(const Flow &other) const {
    assert(this->height == other.height);
    assert(this->bridge == other.bridge);

    if (this->bridge) {
        return this->width/2 + other.width/2 + BRIDGE_EXTRA_SPACING;
    }

    return this->spacing()/2 + other.spacing()/2;
}

/* This method returns extrusion volume per head move unit. */
double
Flow::mm3_per_mm() const {
    if (this->bridge) {
        return (this->width * this->width) * PI/4.0;
    }

    // rectangle with semicircles at the ends
    return this->width * this->height + (this->height*this->height) / 4.0 * (PI-4.0);
}

/* This static method returns bridge width for a given nozzle diameter. */
float
Flow::_bridge_width(float nozzle_diameter, float bridge_flow_ratio) {
    if (bridge_flow_ratio == 1) return nozzle_diameter;  // optimization to avoid sqrt()
    return sqrt(bridge_flow_ratio * (nozzle_diameter*nozzle_diameter));
}

/* This static method returns a sane extrusion width default. */
float
Flow::_auto_width(FlowRole role, float nozzle_diameter, float height) {
    // here we calculate a sane default by matching the flow speed (at the nozzle) and the feed rate
    // shape: rectangle with semicircles at the ends
    float width = ((nozzle_diameter*nozzle_diameter) * PI + (height*height) * (4.0 - PI)) / (4.0 * height);

    float min = nozzle_diameter * 1.05;
    float max = nozzle_diameter * 1.25; // cap width to 1.25x nozzle diameter
    if (role == frExternalPerimeter || role == frSupportMaterial || role == frSupportMaterialInterface) {
        min = max = nozzle_diameter*1.1;
    } else if (role != frInfill) {
        // limit width a bit for sparse infill to avoid unwanted overextrusion.
        max = nozzle_diameter * 1.4;
    }
    if (width > max) width = max;
    if (width < min) width = min;

    return width;
}

/* This static method returns the extrusion width value corresponding to the supplied centerline spacing. */
float
Flow::_width_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge) {
    if (bridge) {
        return spacing - BRIDGE_EXTRA_SPACING;
    }

    // rectangle with semicircles at the ends
    return spacing + OVERLAP_FACTOR * height * (1 - PI/4.0);
}

/// Calculate a new spacing to fill width with possibly integer number of lines,
/// the first and last line being centered at the interval ends.
/// This function possibly increases the spacing, never decreases,
/// and for a narrow width the increase in spacing may become severe,
/// therefore the adjustment is limited to 20% increase.
template <class T>
T
Flow::solid_spacing(const T total_width, const T spacing)
{
    assert(total_width >= 0);
    assert(spacing > 0);
    const int number_of_intervals = floor(total_width / spacing);
    if (number_of_intervals == 0) return spacing;

    T spacing_new = (total_width / number_of_intervals);

    const double factor = (double)spacing_new / (double)spacing;
    assert(factor > 1. - 1e-5);

    // How much could the extrusion width be increased? By 20%.
    // Because of this limit, this method is not idempotent: each run
    // will increment spacing by 20%.
    const double factor_max = 1.2;
    if (factor > factor_max)
        spacing_new = floor((double)spacing * factor_max + 0.5);

    assert((spacing_new * number_of_intervals) <= total_width);

    return spacing_new;
}
template coord_t Flow::solid_spacing<coord_t>(const coord_t total_width, const coord_t spacing);
template coordf_t Flow::solid_spacing<coordf_t>(const coordf_t total_width, const coordf_t spacing);

}
<commit_msg>Code cleanup: Ensure that a floats remain floats all the way through expressions.<commit_after>#include "Flow.hpp"
#include <cmath>
#include <assert.h>

namespace Slic3r {

/* This constructor builds a Flow object from an extrusion width config setting
   and other context properties. */
Flow
Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent &width, float nozzle_diameter, float height, float bridge_flow_ratio) {
    // we need layer height unless it's a bridge
    if (height <= 0 && bridge_flow_ratio == 0) CONFESS("Invalid flow height supplied to new_from_config_width()");

    float w;
    if (bridge_flow_ratio > 0) {
        // if bridge flow was requested, calculate bridge width
        height = w = Flow::_bridge_width(nozzle_diameter, bridge_flow_ratio);
    } else if (!width.percent && width.value == 0) {
        // if user left option to 0, calculate a sane default width
        w = Flow::_auto_width(role, nozzle_diameter, height);
    } else {
        // if user set a manual value, use it
        w = width.get_abs_value(height);
    }

    return Flow(w, height, nozzle_diameter, bridge_flow_ratio > 0);
}

/* This constructor builds a Flow object from a given centerline spacing. */
Flow
Flow::new_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge) {
    // we need layer height unless it's a bridge
    if (height <= 0 && !bridge) CONFESS("Invalid flow height supplied to new_from_spacing()");

    float w = Flow::_width_from_spacing(spacing, nozzle_diameter, height, bridge);
    if (bridge) height = w;
    return Flow(w, height, nozzle_diameter, bridge);
}

/* This method returns the centerline spacing between two adjacent extrusions
   having the same extrusion width (and other properties). */
float
Flow::spacing() const {
    if (this->bridge) {
        return this->width + BRIDGE_EXTRA_SPACING;
    }

    // rectangle with semicircles at the ends
    float min_flow_spacing = this->width - this->height * (1.0 - PI/4.0);
    return this->width - OVERLAP_FACTOR * (this->width - min_flow_spacing);
}

void
Flow::set_spacing(float spacing) {
    this->width = Flow::_width_from_spacing(spacing, this->nozzle_diameter, this->height, this->bridge);
}

/* This method returns the centerline spacing between an extrusion using this
   flow and another one using another flow.
   this->spacing(other) shall return the same value as other.spacing(*this) */
float
Flow::spacing(const Flow &other) const {
    assert(this->height == other.height);
    assert(this->bridge == other.bridge);

    if (this->bridge) {
        return this->width/2.0 + other.width/2.0 + BRIDGE_EXTRA_SPACING;
    }

    return this->spacing()/2.0 + other.spacing()/2.0;
}

/* This method returns extrusion volume per head move unit. */
double
Flow::mm3_per_mm() const {
    if (this->bridge) {
        return (this->width * this->width) * PI/4.0;
    }

    // rectangle with semicircles at the ends
    return this->width * this->height + (this->height*this->height) / 4.0 * (PI-4.0);
}

/* This static method returns bridge width for a given nozzle diameter. */
float
Flow::_bridge_width(float nozzle_diameter, float bridge_flow_ratio) {
    if (bridge_flow_ratio == 1) return nozzle_diameter;  // optimization to avoid sqrt()
    return sqrt(bridge_flow_ratio * (nozzle_diameter*nozzle_diameter));
}

/* This static method returns a sane extrusion width default. */
float
Flow::_auto_width(FlowRole role, float nozzle_diameter, float height) {
    // here we calculate a sane default by matching the flow speed (at the nozzle) and the feed rate
    // shape: rectangle with semicircles at the ends
    float width = ((nozzle_diameter*nozzle_diameter) * PI + (height*height) * (4.0 - PI)) / (4.0 * height);

    float min = nozzle_diameter * 1.05;
    float max = nozzle_diameter * 1.25; // cap width to 1.25x nozzle diameter
    if (role == frExternalPerimeter || role == frSupportMaterial || role == frSupportMaterialInterface) {
        min = max = nozzle_diameter*1.1;
    } else if (role != frInfill) {
        // limit width a bit for sparse infill to avoid unwanted overextrusion.
        max = nozzle_diameter * 1.4;
    }
    if (width > max) width = max;
    if (width < min) width = min;

    return width;
}

/* This static method returns the extrusion width value corresponding to the supplied centerline spacing. */
float
Flow::_width_from_spacing(float spacing, float nozzle_diameter, float height, bool bridge) {
    if (bridge) {
        return spacing - BRIDGE_EXTRA_SPACING;
    }

    // rectangle with semicircles at the ends
    return spacing + OVERLAP_FACTOR * height * (1 - PI/4.0);
}

/// Calculate a new spacing to fill width with possibly integer number of lines,
/// the first and last line being centered at the interval ends.
/// This function possibly increases the spacing, never decreases,
/// and for a narrow width the increase in spacing may become severe,
/// therefore the adjustment is limited to 20% increase.
template <class T>
T
Flow::solid_spacing(const T total_width, const T spacing)
{
    assert(total_width >= 0);
    assert(spacing > 0);
    const int number_of_intervals = floor(total_width / spacing);
    if (number_of_intervals == 0) return spacing;

    T spacing_new = (total_width / number_of_intervals);

    const double factor = (double)spacing_new / (double)spacing;
    assert(factor > 1. - 1e-5);

    // How much could the extrusion width be increased? By 20%.
    // Because of this limit, this method is not idempotent: each run
    // will increment spacing by 20%.
    const double factor_max = 1.2;
    if (factor > factor_max)
        spacing_new = floor((double)spacing * factor_max + 0.5);

    assert((spacing_new * number_of_intervals) <= total_width);

    return spacing_new;
}
template coord_t Flow::solid_spacing<coord_t>(const coord_t total_width, const coord_t spacing);
template coordf_t Flow::solid_spacing<coordf_t>(const coordf_t total_width, const coordf_t spacing);

}
<|endoftext|>


<commit_before>#include <assert.h>
#include <stdio.h>
#include <atomic>
#include <new>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include "mtrace.h"
#include "fstest.h"
#include "libutil.h"
#include "spinbarrier.hh"

extern char _end[];
__thread sigjmp_buf pf_jmpbuf;
__thread int pf_active;

class double_barrier {
  spin_barrier enter_;
  spin_barrier exit_;

public:
  double_barrier() : enter_(2), exit_(2) {}
  void sync() { enter(); exit(); }
  void enter() { enter_.join(); }
  void exit() { exit_.join(); }
};

struct testproc {
  double_barrier setup;
  std::atomic<void (*)(void)> setupf1;
  std::atomic<void (*)(void)> setupf2;

  testproc(void (*s1)(void), void (*s2)(void)) : setupf1(s1), setupf2(s2) {}
  void run() {
    setup.enter();
    setupf1();
    setupf2();
    setup.exit();
  }
};

struct testfunc {
  double_barrier start;
  double_barrier stop;

  std::atomic<int (*)(void)> func;
  std::atomic<int> retval;

  testfunc(int (*f)(void)) : func(f) {}
  void run() {
#ifndef XV6_USER
    errno = 0;
#endif
    start.sync();
    retval = func();
    stop.sync();
  }
};

static void*
testfunc_thread(void* arg)
{
  madvise(0, (size_t) _end, MADV_WILLNEED);
  testfunc* f = (testfunc*) arg;
  f->run();
  return nullptr;
}

static void
run_test(testproc* tp, testfunc* tf, fstest* t, int first_func, bool do_pin)
{
  assert(first_func == 0 || first_func == 1);
  if (do_pin)
    setaffinity(2);

  for (int i = 0; i < 2; i++)
    new (&tp[i]) testproc(t->proc[i].setup_proc, t->setup_procfinal);
  for (int i = 0; i < 2; i++)
    new (&tf[i]) testfunc(t->func[i].call);

  t->setup_common();

  pid_t pids[2] = { 0, 0 };
  for (int p = 0; p < 2; p++) {
    int nfunc = 0;
    for (int f = 0; f < 2; f++)
      if (t->func[f].callproc == p)
        nfunc++;
    if (nfunc == 0)
      continue;

    fflush(stdout);
    if (do_pin) {
      for (int f = 0; f < 2; f++) {
        if (t->func[f].callproc == p) {
          setaffinity(f+2);
          break;
        }
      }
    }

    pids[p] = fork();
    assert(pids[p] >= 0);

    if (pids[p] == 0) {
      // Get all text and data structures
      madvise(0, (size_t) _end, MADV_WILLNEED);

      // Prime the VM system (this must be kept in sync with
      // fs_testgen.py)
      void *r = mmap((void*)0x12345600000, 4 * 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
      if (r == (void*)-1)
        setup_error("mmap (fixed)");
      munmap(r, 4 * 4096);

      r = mmap(0, 4 * 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
      if (r == (void*)-1)
        setup_error("mmap (non-fixed)");
      munmap(r, 4 * 4096);

      // Run setup
      tp[p].run();

      int ndone = 0;
      pthread_t tid[2];
      for (int f = 0; f < 2; f++) {
        if (t->func[f].callproc == p) {
          if (do_pin)
            setaffinity(f);
          ndone++;
          if (ndone == nfunc)
            testfunc_thread(&tf[f]);
          else
            pthread_create(&tid[f], 0, testfunc_thread, (void*) &tf[f]);
        }
      }

      if (nfunc == 2)
        pthread_join(tid[0], nullptr);
      exit(0);
    }
  }

  for (int p = 0; p < 2; p++) if (pids[p]) tp[p].setup.sync();
  t->setup_final();

  for (int i = 0; i < 2; i++) tf[i].start.enter();

  char mtname[64];
  snprintf(mtname, sizeof(mtname), "%s", t->testname);
  mtenable_type(mtrace_record_ascope, mtname);

  for (int i = 0; i < 2; i++) {
    tf[first_func ^ i].start.exit();
    tf[first_func ^ i].stop.enter();
  }

  mtdisable(mtname);

  for (int i = 0; i < 2; i++) tf[i].stop.exit();

  for (int p = 0; p < 2; p++)
    if (pids[p])
      assert(waitpid(pids[p], nullptr, 0) >= 0);

  t->cleanup();
}

static void
pf_handler(int signo)
{
  if (pf_active)
    siglongjmp(pf_jmpbuf, signo);
  // Let the error happen
  signal(signo, SIG_DFL);
}

static bool verbose = false;
static bool check_commutativity = false;
static bool run_threads = false;
static bool check_results = false;
static fstest *cur_test = nullptr;

void
expect_result(const char *varname, long got, long expect)
{
  if (!check_results) return;
  if (got == expect) return;
  auto name = cur_test->testname;
#ifdef XV6_USER
  printf("%s: expected %s == %ld, got %ld\n",
         name, varname, expect, got);
#else
  printf("%s: expected %s == %ld, got %ld (errno %s)\n",
         name, varname, expect, got, strerror(errno));
#endif
}

void
expect_errno(int expect)
{
#ifndef XV6_USER
  if (!check_results) return;
  if (errno == expect) return;
  auto name = cur_test->testname;
  printf("%s: expected errno == %s, got %s\n",
         name, strerror(expect), strerror(errno));
#endif
}

static void
usage(const char* prog)
{
  fprintf(stderr, "Usage: %s [-v] [-c] [-t] [-r] [-n NPARTS] [-p THISPART] [min[-max]]\n", prog);
}

int
main(int ac, char** av)
{
  uint32_t min = 0;
  uint32_t max;
  int nparts = -1;
  int thispart = -1;

  uint32_t ntests = 0;
  for (ntests = min; fstests[ntests].testname; ntests++)
    ;
  max = ntests - 1;

  for (;;) {
    int opt = getopt(ac, av, "vctrp:n:");
    if (opt == -1)
      break;

    switch (opt) {
    case 'v':
      verbose = true;
      break;

    case 'c':
      check_commutativity = true;
      break;

    case 't':
      run_threads = true;
      break;

    case 'r':
      run_threads = true;
      check_results = true;
      break;

    case 'n':
      nparts = atoi(optarg);
      break;

    case 'p':
      thispart = atoi(optarg);
      break;

    default:
      usage(av[0]);
      return -1;
    }
  }

  if (optind < ac) {
    char* dash = strchr(av[optind], '-');
    if (!dash) {
      min = max = atoi(av[optind]);
    } else {
      *dash = '\0';
      if (av[optind])
        min = atoi(av[optind]);
      if (*(dash + 1))
        max = atoi(dash + 1);
    }
  } else if (nparts >= 0 || thispart >= 0) {
    if (nparts < 0 || thispart < 0) {
      usage(av[0]);
      return -1;
    }

    uint32_t partsize = (ntests + nparts - 1) /nparts;
    min = partsize * thispart;
    max = partsize * (thispart + 1) - 1;
  }

  if (!check_commutativity && !run_threads) {
    fprintf(stderr, "Must specify one of -c or -t\n");
    usage(av[0]);
    return -1;
  }

  printf("fstest:");
  if (verbose)
    printf(" verbose");
  if (check_commutativity)
    printf(" check");
  if (run_threads)
    printf(" threads");
  if (check_results)
    printf(" results");
  if (min == 0 && max == ntests - 1)
    printf(" all");
  else if (min == max)
    printf(" %d", min);
  else
    printf(" %d-%d", min, max);
  printf("\n");

  testproc* tp = (testproc*) mmap(nullptr, 4096, PROT_READ | PROT_WRITE,
                                  MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  assert(tp != MAP_FAILED);
  assert(2*sizeof(*tp) <= 4096);

  testfunc* tf = (testfunc*) mmap(nullptr, 4096, PROT_READ | PROT_WRITE,
                                  MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  assert(tf != MAP_FAILED);
  assert(2*sizeof(*tf) <= 4096);

  madvise(0, (size_t) _end, MADV_WILLNEED);

  signal(SIGPIPE, SIG_IGN);
  signal(SIGBUS, pf_handler);
  signal(SIGSEGV, pf_handler);

  for (uint32_t t = min; t <= max && t < ntests; t++) {
    cur_test = &fstests[t];

    if (verbose)
      printf("%s (test %d) starting\n", fstests[t].testname, t);

    if (check_commutativity) {
      run_test(tp, tf, &fstests[t], 0, false);
      int ra0 = tf[0].retval;
      int ra1 = tf[1].retval;

      run_test(tp, tf, &fstests[t], 1, false);
      int rb0 = tf[0].retval;
      int rb1 = tf[1].retval;

      if (ra0 == rb0 && ra1 == rb1) {
        if (verbose)
          printf("%s: commutes: %s->%d %s->%d\n",
                 fstests[t].testname,
                 fstests[t].func[0].callname, ra0, fstests[t].func[1].callname, ra1);
      } else {
        printf("%s: diverges: %s->%d %s->%d vs %s->%d %s->%d\n",
               fstests[t].testname,
               fstests[t].func[0].callname, ra0, fstests[t].func[1].callname, ra1,
               fstests[t].func[1].callname, rb1, fstests[t].func[0].callname, rb0);
      }
    }

    if (run_threads) {
      run_test(tp, tf, &fstests[t], 0, true);
    }
  }

  printf("fstest: done\n");
}
<commit_msg>fstest: Accept a test case name on the command line<commit_after>#include <assert.h>
#include <stdio.h>
#include <atomic>
#include <new>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <pthread.h>
#include <signal.h>
#include <setjmp.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include "mtrace.h"
#include "fstest.h"
#include "libutil.h"
#include "spinbarrier.hh"

extern char _end[];
__thread sigjmp_buf pf_jmpbuf;
__thread int pf_active;

class double_barrier {
  spin_barrier enter_;
  spin_barrier exit_;

public:
  double_barrier() : enter_(2), exit_(2) {}
  void sync() { enter(); exit(); }
  void enter() { enter_.join(); }
  void exit() { exit_.join(); }
};

struct testproc {
  double_barrier setup;
  std::atomic<void (*)(void)> setupf1;
  std::atomic<void (*)(void)> setupf2;

  testproc(void (*s1)(void), void (*s2)(void)) : setupf1(s1), setupf2(s2) {}
  void run() {
    setup.enter();
    setupf1();
    setupf2();
    setup.exit();
  }
};

struct testfunc {
  double_barrier start;
  double_barrier stop;

  std::atomic<int (*)(void)> func;
  std::atomic<int> retval;

  testfunc(int (*f)(void)) : func(f) {}
  void run() {
#ifndef XV6_USER
    errno = 0;
#endif
    start.sync();
    retval = func();
    stop.sync();
  }
};

static void*
testfunc_thread(void* arg)
{
  madvise(0, (size_t) _end, MADV_WILLNEED);
  testfunc* f = (testfunc*) arg;
  f->run();
  return nullptr;
}

static void
run_test(testproc* tp, testfunc* tf, fstest* t, int first_func, bool do_pin)
{
  assert(first_func == 0 || first_func == 1);
  if (do_pin)
    setaffinity(2);

  for (int i = 0; i < 2; i++)
    new (&tp[i]) testproc(t->proc[i].setup_proc, t->setup_procfinal);
  for (int i = 0; i < 2; i++)
    new (&tf[i]) testfunc(t->func[i].call);

  t->setup_common();

  pid_t pids[2] = { 0, 0 };
  for (int p = 0; p < 2; p++) {
    int nfunc = 0;
    for (int f = 0; f < 2; f++)
      if (t->func[f].callproc == p)
        nfunc++;
    if (nfunc == 0)
      continue;

    fflush(stdout);
    if (do_pin) {
      for (int f = 0; f < 2; f++) {
        if (t->func[f].callproc == p) {
          setaffinity(f+2);
          break;
        }
      }
    }

    pids[p] = fork();
    assert(pids[p] >= 0);

    if (pids[p] == 0) {
      // Get all text and data structures
      madvise(0, (size_t) _end, MADV_WILLNEED);

      // Prime the VM system (this must be kept in sync with
      // fs_testgen.py)
      void *r = mmap((void*)0x12345600000, 4 * 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
      if (r == (void*)-1)
        setup_error("mmap (fixed)");
      munmap(r, 4 * 4096);

      r = mmap(0, 4 * 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
      if (r == (void*)-1)
        setup_error("mmap (non-fixed)");
      munmap(r, 4 * 4096);

      // Run setup
      tp[p].run();

      int ndone = 0;
      pthread_t tid[2];
      for (int f = 0; f < 2; f++) {
        if (t->func[f].callproc == p) {
          if (do_pin)
            setaffinity(f);
          ndone++;
          if (ndone == nfunc)
            testfunc_thread(&tf[f]);
          else
            pthread_create(&tid[f], 0, testfunc_thread, (void*) &tf[f]);
        }
      }

      if (nfunc == 2)
        pthread_join(tid[0], nullptr);
      exit(0);
    }
  }

  for (int p = 0; p < 2; p++) if (pids[p]) tp[p].setup.sync();
  t->setup_final();

  for (int i = 0; i < 2; i++) tf[i].start.enter();

  char mtname[64];
  snprintf(mtname, sizeof(mtname), "%s", t->testname);
  mtenable_type(mtrace_record_ascope, mtname);

  for (int i = 0; i < 2; i++) {
    tf[first_func ^ i].start.exit();
    tf[first_func ^ i].stop.enter();
  }

  mtdisable(mtname);

  for (int i = 0; i < 2; i++) tf[i].stop.exit();

  for (int p = 0; p < 2; p++)
    if (pids[p])
      assert(waitpid(pids[p], nullptr, 0) >= 0);

  t->cleanup();
}

static void
pf_handler(int signo)
{
  if (pf_active)
    siglongjmp(pf_jmpbuf, signo);
  // Let the error happen
  signal(signo, SIG_DFL);
}

static bool verbose = false;
static bool check_commutativity = false;
static bool run_threads = false;
static bool check_results = false;
static fstest *cur_test = nullptr;

void
expect_result(const char *varname, long got, long expect)
{
  if (!check_results) return;
  if (got == expect) return;
  auto name = cur_test->testname;
#ifdef XV6_USER
  printf("%s: expected %s == %ld, got %ld\n",
         name, varname, expect, got);
#else
  printf("%s: expected %s == %ld, got %ld (errno %s)\n",
         name, varname, expect, got, strerror(errno));
#endif
}

void
expect_errno(int expect)
{
#ifndef XV6_USER
  if (!check_results) return;
  if (errno == expect) return;
  auto name = cur_test->testname;
  printf("%s: expected errno == %s, got %s\n",
         name, strerror(expect), strerror(errno));
#endif
}

static void
usage(const char* prog)
{
  fprintf(stderr, "Usage: %s [-v] [-c] [-t] [-r] [-n NPARTS] [-p THISPART] [min[-max]]\n", prog);
}

int
main(int ac, char** av)
{
  uint32_t min = 0;
  uint32_t max;
  int nparts = -1;
  int thispart = -1;

  uint32_t ntests = 0;
  for (ntests = min; fstests[ntests].testname; ntests++)
    ;
  max = ntests - 1;

  for (;;) {
    int opt = getopt(ac, av, "vctrp:n:");
    if (opt == -1)
      break;

    switch (opt) {
    case 'v':
      verbose = true;
      break;

    case 'c':
      check_commutativity = true;
      break;

    case 't':
      run_threads = true;
      break;

    case 'r':
      run_threads = true;
      check_results = true;
      break;

    case 'n':
      nparts = atoi(optarg);
      break;

    case 'p':
      thispart = atoi(optarg);
      break;

    default:
      usage(av[0]);
      return -1;
    }
  }

  if (optind < ac) {
    bool found = false;
    for (uint32_t t = 0; t < ntests && !found; t++) {
      if (strcmp(av[optind], fstests[t].testname) == 0) {
        min = max = t;
        found = true;
      }
    }

    if (!found) {
      char* dash = strchr(av[optind], '-');
      if (!dash) {
        min = max = atoi(av[optind]);
      } else {
        *dash = '\0';
        if (av[optind])
          min = atoi(av[optind]);
        if (*(dash + 1))
          max = atoi(dash + 1);
      }
    }
  } else if (nparts >= 0 || thispart >= 0) {
    if (nparts < 0 || thispart < 0) {
      usage(av[0]);
      return -1;
    }

    uint32_t partsize = (ntests + nparts - 1) /nparts;
    min = partsize * thispart;
    max = partsize * (thispart + 1) - 1;
  }

  if (!check_commutativity && !run_threads) {
    fprintf(stderr, "Must specify one of -c or -t\n");
    usage(av[0]);
    return -1;
  }

  printf("fstest:");
  if (verbose)
    printf(" verbose");
  if (check_commutativity)
    printf(" check");
  if (run_threads)
    printf(" threads");
  if (check_results)
    printf(" results");
  if (min == 0 && max == ntests - 1)
    printf(" all");
  else if (min == max)
    printf(" %d", min);
  else
    printf(" %d-%d", min, max);
  printf("\n");

  testproc* tp = (testproc*) mmap(nullptr, 4096, PROT_READ | PROT_WRITE,
                                  MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  assert(tp != MAP_FAILED);
  assert(2*sizeof(*tp) <= 4096);

  testfunc* tf = (testfunc*) mmap(nullptr, 4096, PROT_READ | PROT_WRITE,
                                  MAP_SHARED | MAP_ANONYMOUS, -1, 0);
  assert(tf != MAP_FAILED);
  assert(2*sizeof(*tf) <= 4096);

  madvise(0, (size_t) _end, MADV_WILLNEED);

  signal(SIGPIPE, SIG_IGN);
  signal(SIGBUS, pf_handler);
  signal(SIGSEGV, pf_handler);

  for (uint32_t t = min; t <= max && t < ntests; t++) {
    cur_test = &fstests[t];

    if (verbose)
      printf("%s (test %d) starting\n", fstests[t].testname, t);

    if (check_commutativity) {
      run_test(tp, tf, &fstests[t], 0, false);
      int ra0 = tf[0].retval;
      int ra1 = tf[1].retval;

      run_test(tp, tf, &fstests[t], 1, false);
      int rb0 = tf[0].retval;
      int rb1 = tf[1].retval;

      if (ra0 == rb0 && ra1 == rb1) {
        if (verbose)
          printf("%s: commutes: %s->%d %s->%d\n",
                 fstests[t].testname,
                 fstests[t].func[0].callname, ra0, fstests[t].func[1].callname, ra1);
      } else {
        printf("%s: diverges: %s->%d %s->%d vs %s->%d %s->%d\n",
               fstests[t].testname,
               fstests[t].func[0].callname, ra0, fstests[t].func[1].callname, ra1,
               fstests[t].func[1].callname, rb1, fstests[t].func[0].callname, rb0);
      }
    }

    if (run_threads) {
      run_test(tp, tf, &fstests[t], 0, true);
    }
  }

  printf("fstest: done\n");
}
<|endoftext|>


<commit_before>/** @file gsGeometry.hpp

    @brief Provides implementation of Geometry default operatiions.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): A. Mantzaflaris
*/

#pragma once

#include <gsCore/gsBasis.h>
#include <gsUtils/gsMesh/gsMesh.h>
#include <gsCore/gsFuncData.h>

#include <gsCore/gsGeometrySlice.h>

namespace gismo
{

template<class T>
gsMatrix<T> gsGeometry<T>::parameterCenter( const boxCorner& bc )
{
    gsMatrix<T> supp = parameterRange();
    const index_t dim = supp.rows();
    gsMatrix<T> coordinates(dim,1);
    gsVector<bool> boxPar = bc.parameters(dim);
    for (index_t d=0; d<dim;++d)
    {
        if (boxPar(d))
            coordinates(d,0) = supp(d,1);
        else
            coordinates(d,0) = supp(d,0);
    }
    return coordinates;
}

template<class T>
gsMatrix<T> gsGeometry<T>::parameterCenter( const boxSide& bc )
{
    gsMatrix<T> supp = parameterRange();
    const index_t dim = supp.rows();
    gsMatrix<T> coordinates(dim,1);
    const index_t dir = bc.direction();
    for (index_t d=0; d<dim;++d)
    {
        if (d != dir)
            coordinates(d,0) = ( supp(d,1) + supp(d,0) ) / T(2);
        else if (bc.parameter())
            coordinates(d,0) = supp(d,1);
        else
            coordinates(d,0) = supp(d,0);
    }
    return coordinates;
}

    /*
template<class T>
boxSide gsGeometry<T>::sideOf( const gsVector<T> & u,  )
{
    // get the indices of the coefficients which lie on the boundary
    gsMatrix<unsigned > allBnd = m_basis->allBoundary();
    gsMatrix<T> bndCoeff(allBnd.rows(), m_coefs.rows());

    // extract the indices of the boundary coefficients
    for(index_t r = 0; r < allBnd.rows(); r++)
        bndCoeff.row(r) = m_coefs.row(allBnd(r,0));

    for(size_t size = 0; size < allBnd.rows(); size++)
        if(boundaryPatch1[size] == 1)
            interfaceIndicesPatch1.push_back(allBnd(size, 0)); // get the indices of the coefficients on patch 1 which lie on the common interface

    boxSide side;

    for(unsigned index = 1; index <= nBoundaries; index++) {
        int contained = 0;
        side.m_index = index;

        gsMatrix<unsigned> bnd = m_basis->boundary(side);

        for(size_t i = 0; i < interfaceIndicesPatch1.size(); i++)
        {
            gsInfo << "index: " << interfaceIndicesPatch1[i] << "\n";
            for (int j = 0; j < bnd.rows(); j++)
            {
                if(bnd(j, 0) == interfaceIndicesPatch1[i])
                    contained++;
            }
        }

        if(contained == bnd.rows())
            break;

        //gsInfo << "indices of boundary : " << bnd << "\n";
    }
}
     */

template<class T>
typename gsGeometry<T>::uPtr
gsGeometry<T>::boundary(boxSide const& s) const
{
    gsMatrix<unsigned> ind = this->basis().boundary(s); // get indices of the boundary DOF
    gsMatrix<T> coeffs (ind.size(), geoDim()); // create matrix for boundary coefficients

    for (index_t i=0; i != ind.size(); i++ )
    {
        coeffs.row(i) = m_coefs.row( (ind)(i,0) );
    }

    typename gsBasis<T>::uPtr Bs = this->basis().boundaryBasis(s);  // Basis for boundary side s
    uPtr bgeo = Bs->makeGeometry( give(coeffs) );

    return bgeo;
}

template<class T>
void gsGeometry<T>::evaluateMesh(gsMesh<T>& mesh) const
{
    const int pDim = parDim();
    const int gDim = geoDim();

    gsMatrix<T> tmp;

    // For all vertices of the mesh, push forward the value by the
    // geometry mapping
    for (size_t i = 0; i!= mesh.numVertices(); ++i)
    {
        eval_into( mesh.vertex(i).topRows(pDim), tmp );
        mesh.vertex(i).topRows( gDim ) = tmp;
    }
}
template<class T>
std::vector<gsGeometry<T>* > gsGeometry<T>::uniformSplit(index_t) const
{
    GISMO_NO_IMPLEMENTATION
}

template<class T>
gsGeometrySlice<T> gsGeometry<T>::getIsoParametricSlice(index_t dir_fixed, T par) const
{
    return gsGeometrySlice<T>(this,dir_fixed,par);
}

template<class T>
typename gsMatrix<T>::RowXpr
gsGeometry<T>::coefAtCorner(boxCorner const & c)
{
    return this->m_coefs.row(this->basis().functionAtCorner(c));
}

template<class T>
typename gsMatrix<T>::ConstRowXpr
gsGeometry<T>::coefAtCorner(boxCorner const & c) const
{
    return this->m_coefs.row(this->basis().functionAtCorner(c));
}

template<class T>
void gsGeometry<T>::invertPoints(const gsMatrix<T> & points,
                                 gsMatrix<T> & result,
                                 const T accuracy) const
{
    result.resize(parDim(), points.cols() );
    gsVector<T> arg;
    for ( index_t i = 0; i!= points.cols(); ++i)
    {
        arg = parameterCenter();
        //int iter =
        this->newtonRaphson(points.col(i), arg, true, accuracy, 100);
        result.col(i) = arg;
    }
}

template<class T>
void gsGeometry<T>::merge(gsGeometry *)
{ GISMO_NO_IMPLEMENTATION }

template<class T>
void gsGeometry<T>::toMesh(gsMesh<T> &, int) const
{ GISMO_NO_IMPLEMENTATION }

template<class T>
void gsGeometry<T>::outerNormal_into(const gsMatrix<T>&, gsMatrix<T> &) const
{ GISMO_NO_IMPLEMENTATION }

template<class T>
std::vector<gsGeometry<T> *> gsGeometry<T>:: boundary() const
{
    // TO DO: get boundary curves, using basis().boundary();
    GISMO_NO_IMPLEMENTATION
}

template<class T>
void gsGeometry<T>::degreeElevate(short_t const i, short_t const dir)
{
    typename gsBasis<T>::uPtr b = m_basis->clone();

    if ( dir == -1 )
        b->degreeElevate(i);
    else if (dir < parDim() )
        b->degreeElevate(i, dir);
    else
        GISMO_ERROR("Invalid direction "<< dir <<" to elevate.");

    gsMatrix<T> iVals, iPts = b->anchors();
    this->eval_into(iPts, iVals);
    typename gsGeometry<T>::uPtr g = b->interpolateData(iVals, iPts);

    std::swap(m_basis, g->m_basis);
    g->coefs().swap(this->coefs());
}

template<class T>
void gsGeometry<T>::degreeReduce(short_t const i, short_t const dir)
{
    typename gsBasis<T>::uPtr b = m_basis->clone();

    if ( dir == -1 )
        b->degreeReduce(i);
    else if (dir < parDim() )
        b->component(dir).degreeReduce(i);
    else
        GISMO_ERROR("Invalid direction "<< dir <<" to degree-reduce.");

    gsMatrix<T> iVals, iPts = b->anchors();
    this->eval_into(iPts, iVals);
    typename gsGeometry<T>::uPtr g = b->interpolateData(iVals, iPts);

    std::swap(m_basis, g->m_basis);
    g->coefs().swap(this->coefs());
}

template<class T>
gsMatrix<T>
gsGeometry<T>::hessian(const gsMatrix<T>& u, unsigned coord) const
{
    static const unsigned d = this->m_basis->dim();

    gsMatrix<T> B, DD(d,d), tmp(d,d);
    gsMatrix<unsigned> ind;

    // coefficient matrix row k = coef. of basis function k
    const gsMatrix<T>& C = this->m_coefs;
    // col j = nonzero second derivatives at column point u(..,j)
    m_basis->deriv2_into(u, B) ;
    // col j = indices of active functions at column point u(..,j)
    m_basis->active_into(u, ind);

    DD.setZero();
    unsigned j=0;// just one column
    //for ( unsigned j=0; j< u.cols(); j++ ) // for all points (columns of u)
    for ( index_t i=0; i< ind.rows() ; i++ ) // for all non-zero basis functions)
    {
        unsigned m=i*d;
        unsigned r= ind.rows()*d + i*d*(d-1)/2;
        //construct the Hessian of basis function ind(i,0)
        for (unsigned k=0; k<d; ++k ) // for all rows
        {
            tmp(k,k) = B(m+k,j);
            for (unsigned l=k+1; l<d; ++l ) // for all cols
                tmp(k,l) = tmp(l,k) = B(r++,0);
        }
        DD += C(ind(i,j), coord) * tmp;
    }

    return DD;
}

template <typename T>
void extractRows( const gsMatrix<T> &in, typename gsMatrix<unsigned>::constColumn actives, gsMatrix<T> &out)
{
    out.resize(actives.rows(), in.cols());
    for (index_t r=0; r<actives.rows();++r)
        out.row(r)=in.row(actives(r,0));
}

template <class T>
void
gsGeometry<T>::compute(const gsMatrix<T> & in, gsFuncData<T> & out) const
{

    const unsigned flags = out.flags | NEED_ACTIVE;
    const index_t  numPt = in.cols();
    const index_t  numCo = m_coefs.cols();

    gsFuncData<T> tmp(flags);
    this->basis().compute(in, tmp);

    out.values.resize(out.maxDeriv()+1);
    out.dim.first  = tmp.dim.first;
    out.dim.second = numCo;
    if ( flags & SAME_ELEMENT )
    {
        gsMatrix<T> coefM;
        extractRows(m_coefs,tmp.active(0),coefM);

        if (flags & NEED_VALUE)
            out.values[0]=coefM.transpose()*tmp.values[0];
        if (flags & NEED_DERIV)
        {
            const index_t derS = tmp.derivSize();
            out.values[1].resize(derS*numCo,numPt);
            for (index_t p=0; p< numPt; ++p)
                out.values[1].reshapeCol(p, derS, numCo) = tmp.deriv(p)*coefM;
        }
        if (flags & NEED_DERIV2)
        {
            const index_t derS = tmp.deriv2Size();
            out.values[2].resize(derS*numCo,numPt);
            for (index_t p=0; p< numPt; ++p)
                out.values[2].reshapeCol(p, derS, numCo) = tmp.deriv2(p)*coefM;
        }
    } else
    {
        gsMatrix<T> coefM;
        const index_t derS = tmp.derivSize();
        const index_t der2S = tmp.deriv2Size();

        if (flags & NEED_VALUE)  out.values[0].resize(numCo,numPt);
        if (flags & NEED_DERIV)  out.values[1].resize(numCo*derS,numPt);
        if (flags & NEED_DERIV2) out.values[2].resize(numCo*der2S,numPt);

        for (index_t p=0; p<numPt;++p)
        {
            extractRows(m_coefs,tmp.active(p),coefM);
            if (flags & NEED_VALUE)
                out.values[0].reshapeCol(p,1,numCo) = tmp.eval(p)*coefM;
            if (flags & NEED_DERIV)
                out.values[1].reshapeCol(p, derS, numCo) = tmp.deriv(p)*coefM;
            if (flags & NEED_DERIV2)
                out.values[2].reshapeCol(p, der2S, numCo) = tmp.deriv2(p)*coefM;
        }
    }
}

template<class T>
std::vector<boxSide> gsGeometry<T>::locateOn(const gsMatrix<T> & u, gsVector<bool> & onGeo, gsMatrix<T> & preIm, bool lookForBoundary, real_t tol) const
{
    onGeo.resize(u.cols());
    std::vector<boxSide> sides(u.cols());

    for(index_t i = 0; i < onGeo.size(); i++)
        onGeo(i) = false;

    preIm.resize(geoDim(), u.cols());
    gsMatrix<T> pr = this->parameterRange(), tmp;

    for(index_t i = 0; i < u.cols(); i++)
    {
        this->invertPoints(u.col(i), tmp, tol);
        pr = this->parameterRange();
        //if ((tmp.array() >= pr.col(0).array()).all()
        //    && (tmp.array() <= pr.col(1).array()).all())
        if ((tmp.array() >= pr.col(0).array() - 1.e-4).all()
             && (tmp.array() <= pr.col(1).array() + 1.e-4).all()) // be careful! if u is on the boundary then we may get a wrong result
            // the tolerance is due to imprecisions in the geometry map. E.g. If a circle is rotated then the corner need
            // not to lie exactly on the interface of the neighbour patch since we use only B-splines for the modelling
            // TODO: Maybe find a better solution!
        {
            onGeo(i) = true;
            preIm.col(i) = tmp;

            if (lookForBoundary == true)
            {
                boxSide s;
                for (int d = 0; d < geoDim(); d++) {
                    if ((math::abs(tmp(d, 0) - pr(d, 0)) < tol))
                    {
                        s.m_index = 2*d+1; // lower
                        break;
                    }

                    if ((math::abs(tmp(d, 0) - pr(d, 1)) < tol))
                    {
                        s.m_index = 2 * d + 2; // upper
                        break;
                    }
                }
                sides[i] = s;
            }
        }
    }

    return sides;
}

} // namespace gismo
<commit_msg>fix in geometry<commit_after>/** @file gsGeometry.hpp

    @brief Provides implementation of Geometry default operatiions.

    This file is part of the G+Smo library.

    This Source Code Form is subject to the terms of the Mozilla Public
    License, v. 2.0. If a copy of the MPL was not distributed with this
    file, You can obtain one at http://mozilla.org/MPL/2.0/.

    Author(s): A. Mantzaflaris
*/

#pragma once

#include <gsCore/gsBasis.h>
#include <gsUtils/gsMesh/gsMesh.h>
#include <gsCore/gsFuncData.h>

#include <gsCore/gsGeometrySlice.h>

namespace gismo
{

template<class T>
gsMatrix<T> gsGeometry<T>::parameterCenter( const boxCorner& bc )
{
    gsMatrix<T> supp = parameterRange();
    const index_t dim = supp.rows();
    gsMatrix<T> coordinates(dim,1);
    gsVector<bool> boxPar = bc.parameters(dim);
    for (index_t d=0; d<dim;++d)
    {
        if (boxPar(d))
            coordinates(d,0) = supp(d,1);
        else
            coordinates(d,0) = supp(d,0);
    }
    return coordinates;
}

template<class T>
gsMatrix<T> gsGeometry<T>::parameterCenter( const boxSide& bc )
{
    gsMatrix<T> supp = parameterRange();
    const index_t dim = supp.rows();
    gsMatrix<T> coordinates(dim,1);
    const index_t dir = bc.direction();
    for (index_t d=0; d<dim;++d)
    {
        if (d != dir)
            coordinates(d,0) = ( supp(d,1) + supp(d,0) ) / T(2);
        else if (bc.parameter())
            coordinates(d,0) = supp(d,1);
        else
            coordinates(d,0) = supp(d,0);
    }
    return coordinates;
}

    /*
template<class T>
boxSide gsGeometry<T>::sideOf( const gsVector<T> & u,  )
{
    // get the indices of the coefficients which lie on the boundary
    gsMatrix<unsigned > allBnd = m_basis->allBoundary();
    gsMatrix<T> bndCoeff(allBnd.rows(), m_coefs.rows());

    // extract the indices of the boundary coefficients
    for(index_t r = 0; r < allBnd.rows(); r++)
        bndCoeff.row(r) = m_coefs.row(allBnd(r,0));

    for(size_t size = 0; size < allBnd.rows(); size++)
        if(boundaryPatch1[size] == 1)
            interfaceIndicesPatch1.push_back(allBnd(size, 0)); // get the indices of the coefficients on patch 1 which lie on the common interface

    boxSide side;

    for(unsigned index = 1; index <= nBoundaries; index++) {
        int contained = 0;
        side.m_index = index;

        gsMatrix<unsigned> bnd = m_basis->boundary(side);

        for(size_t i = 0; i < interfaceIndicesPatch1.size(); i++)
        {
            gsInfo << "index: " << interfaceIndicesPatch1[i] << "\n";
            for (int j = 0; j < bnd.rows(); j++)
            {
                if(bnd(j, 0) == interfaceIndicesPatch1[i])
                    contained++;
            }
        }

        if(contained == bnd.rows())
            break;

        //gsInfo << "indices of boundary : " << bnd << "\n";
    }
}
     */

template<class T>
typename gsGeometry<T>::uPtr
gsGeometry<T>::boundary(boxSide const& s) const
{
    gsMatrix<unsigned> ind = this->basis().boundary(s); // get indices of the boundary DOF
    gsMatrix<T> coeffs (ind.size(), geoDim()); // create matrix for boundary coefficients

    for (index_t i=0; i != ind.size(); i++ )
    {
        coeffs.row(i) = m_coefs.row( (ind)(i,0) );
    }

    typename gsBasis<T>::uPtr Bs = this->basis().boundaryBasis(s);  // Basis for boundary side s
    uPtr bgeo = Bs->makeGeometry( give(coeffs) );

    return bgeo;
}

template<class T>
void gsGeometry<T>::evaluateMesh(gsMesh<T>& mesh) const
{
    const int pDim = parDim();
    const int gDim = geoDim();

    gsMatrix<T> tmp;

    // For all vertices of the mesh, push forward the value by the
    // geometry mapping
    for (size_t i = 0; i!= mesh.numVertices(); ++i)
    {
        eval_into( mesh.vertex(i).topRows(pDim), tmp );
        mesh.vertex(i).topRows( gDim ) = tmp;
    }
}
template<class T>
std::vector<gsGeometry<T>* > gsGeometry<T>::uniformSplit(index_t) const
{
    GISMO_NO_IMPLEMENTATION
}

template<class T>
gsGeometrySlice<T> gsGeometry<T>::getIsoParametricSlice(index_t dir_fixed, T par) const
{
    return gsGeometrySlice<T>(this,dir_fixed,par);
}

template<class T>
typename gsMatrix<T>::RowXpr
gsGeometry<T>::coefAtCorner(boxCorner const & c)
{
    return this->m_coefs.row(this->basis().functionAtCorner(c));
}

template<class T>
typename gsMatrix<T>::ConstRowXpr
gsGeometry<T>::coefAtCorner(boxCorner const & c) const
{
    return this->m_coefs.row(this->basis().functionAtCorner(c));
}

template<class T>
void gsGeometry<T>::invertPoints(const gsMatrix<T> & points,
                                 gsMatrix<T> & result,
                                 const T accuracy) const
{
    result.resize(parDim(), points.cols() );
    gsVector<T> arg;
    for ( index_t i = 0; i!= points.cols(); ++i)
    {
        arg = parameterCenter();
        //int iter =
        this->newtonRaphson(points.col(i), arg, true, accuracy, 100);
        result.col(i) = arg;
    }
}

template<class T>
void gsGeometry<T>::merge(gsGeometry *)
{ GISMO_NO_IMPLEMENTATION }

template<class T>
void gsGeometry<T>::toMesh(gsMesh<T> &, int) const
{ GISMO_NO_IMPLEMENTATION }

template<class T>
void gsGeometry<T>::outerNormal_into(const gsMatrix<T>&, gsMatrix<T> &) const
{ GISMO_NO_IMPLEMENTATION }

template<class T>
std::vector<gsGeometry<T> *> gsGeometry<T>:: boundary() const
{
    // TO DO: get boundary curves, using basis().boundary();
    GISMO_NO_IMPLEMENTATION
}

template<class T>
void gsGeometry<T>::degreeElevate(short_t const i, short_t const dir)
{
    typename gsBasis<T>::uPtr b = m_basis->clone();

    if ( dir == -1 )
        b->degreeElevate(i);
    else if (dir < parDim() )
        b->degreeElevate(i, dir);
    else
        GISMO_ERROR("Invalid direction "<< dir <<" to elevate.");

    gsMatrix<T> iVals, iPts = b->anchors();
    this->eval_into(iPts, iVals);
    typename gsGeometry<T>::uPtr g = b->interpolateData(iVals, iPts);

    std::swap(m_basis, g->m_basis);
    g->coefs().swap(this->coefs());
}

template<class T>
void gsGeometry<T>::degreeReduce(short_t const i, short_t const dir)
{
    typename gsBasis<T>::uPtr b = m_basis->clone();

    if ( dir == -1 )
        b->degreeReduce(i);
    else if (dir < parDim() )
        b->component(dir).degreeReduce(i);
    else
        GISMO_ERROR("Invalid direction "<< dir <<" to degree-reduce.");

    gsMatrix<T> iVals, iPts = b->anchors();
    this->eval_into(iPts, iVals);
    typename gsGeometry<T>::uPtr g = b->interpolateData(iVals, iPts);

    std::swap(m_basis, g->m_basis);
    g->coefs().swap(this->coefs());
}

template<class T>
gsMatrix<T>
gsGeometry<T>::hessian(const gsMatrix<T>& u, unsigned coord) const
{
    static const unsigned d = this->m_basis->dim();

    gsMatrix<T> B, DD(d,d), tmp(d,d);
    gsMatrix<unsigned> ind;

    // coefficient matrix row k = coef. of basis function k
    const gsMatrix<T>& C = this->m_coefs;
    // col j = nonzero second derivatives at column point u(..,j)
    m_basis->deriv2_into(u, B) ;
    // col j = indices of active functions at column point u(..,j)
    m_basis->active_into(u, ind);

    DD.setZero();
    unsigned j=0;// just one column
    //for ( unsigned j=0; j< u.cols(); j++ ) // for all points (columns of u)
    for ( index_t i=0; i< ind.rows() ; i++ ) // for all non-zero basis functions)
    {
        unsigned m=i*d;
        unsigned r= ind.rows()*d + i*d*(d-1)/2;
        //construct the Hessian of basis function ind(i,0)
        for (unsigned k=0; k<d; ++k ) // for all rows
        {
            tmp(k,k) = B(m+k,j);
            for (unsigned l=k+1; l<d; ++l ) // for all cols
                tmp(k,l) = tmp(l,k) = B(r++,0);
        }
        DD += C(ind(i,j), coord) * tmp;
    }

    return DD;
}

template <typename T>
void extractRows( const gsMatrix<T> &in, typename gsMatrix<unsigned>::constColumn actives, gsMatrix<T> &out)
{
    out.resize(actives.rows(), in.cols());
    for (index_t r=0; r<actives.rows();++r)
        out.row(r)=in.row(actives(r,0));
}

template <class T>
void
gsGeometry<T>::compute(const gsMatrix<T> & in, gsFuncData<T> & out) const
{
    const unsigned flags = out.flags | NEED_ACTIVE;
    const index_t  numPt = in.cols();
    const index_t  numCo = m_coefs.cols();

    gsFuncData<T> tmp(flags);
    this->basis().compute(in, tmp);

    out.values.resize(out.maxDeriv()+1);
    out.dim.first  = tmp.dim.first;
    out.dim.second = numCo;
    if ( flags & SAME_ELEMENT )
    {
        gsMatrix<T> coefM;
        extractRows(m_coefs,tmp.active(0),coefM);

        if (flags & NEED_VALUE)
            out.values[0]=coefM.transpose()*tmp.values[0];
        if (flags & NEED_DERIV)
        {
            const index_t derS = tmp.derivSize();
            out.values[1].resize(derS*numCo,numPt);
            for (index_t p=0; p< numPt; ++p)
                out.values[1].reshapeCol(p, derS, numCo) = tmp.deriv(p)*coefM;
        }
        if (flags & NEED_DERIV2)
        {
            const index_t derS = tmp.deriv2Size();
            out.values[2].resize(derS*numCo,numPt);
            for (index_t p=0; p< numPt; ++p)
                out.values[2].reshapeCol(p, derS, numCo) = tmp.deriv2(p)*coefM;
        }
        if (flags & NEED_ACTIVE)
            this->active_into(in.col(0), out.actives);
    }
    else
    {
        gsMatrix<T> coefM;
        const index_t derS = tmp.derivSize();
        const index_t der2S = tmp.deriv2Size();

        if (flags & NEED_VALUE)  out.values[0].resize(numCo,numPt);
        if (flags & NEED_DERIV)  out.values[1].resize(numCo*derS,numPt);
        if (flags & NEED_DERIV2) out.values[2].resize(numCo*der2S,numPt);
        if (flags & NEED_ACTIVE) this->active_into(in, out.actives);

        for (index_t p=0; p<numPt;++p)
        {
            extractRows(m_coefs,tmp.active(p),coefM);
            if (flags & NEED_VALUE)
                out.values[0].reshapeCol(p,1,numCo) = tmp.eval(p)*coefM;
            if (flags & NEED_DERIV)
                out.values[1].reshapeCol(p, derS, numCo) = tmp.deriv(p)*coefM;
            if (flags & NEED_DERIV2)
                out.values[2].reshapeCol(p, der2S, numCo) = tmp.deriv2(p)*coefM;
        }
    }
}

template<class T>
std::vector<boxSide> gsGeometry<T>::locateOn(const gsMatrix<T> & u, gsVector<bool> & onGeo, gsMatrix<T> & preIm, bool lookForBoundary, real_t tol) const
{
    onGeo.resize(u.cols());
    std::vector<boxSide> sides(u.cols());

    for(index_t i = 0; i < onGeo.size(); i++)
        onGeo(i) = false;

    preIm.resize(geoDim(), u.cols());
    gsMatrix<T> pr = this->parameterRange(), tmp;

    for(index_t i = 0; i < u.cols(); i++)
    {
        this->invertPoints(u.col(i), tmp, tol);
        pr = this->parameterRange();
        //if ((tmp.array() >= pr.col(0).array()).all()
        //    && (tmp.array() <= pr.col(1).array()).all())
        if ((tmp.array() >= pr.col(0).array() - 1.e-4).all()
             && (tmp.array() <= pr.col(1).array() + 1.e-4).all()) // be careful! if u is on the boundary then we may get a wrong result
            // the tolerance is due to imprecisions in the geometry map. E.g. If a circle is rotated then the corner need
            // not to lie exactly on the interface of the neighbour patch since we use only B-splines for the modelling
            // TODO: Maybe find a better solution!
        {
            onGeo(i) = true;
            preIm.col(i) = tmp;

            if (lookForBoundary == true)
            {
                boxSide s;
                for (int d = 0; d < geoDim(); d++) {
                    if ((math::abs(tmp(d, 0) - pr(d, 0)) < tol))
                    {
                        s.m_index = 2*d+1; // lower
                        break;
                    }

                    if ((math::abs(tmp(d, 0) - pr(d, 1)) < tol))
                    {
                        s.m_index = 2 * d + 2; // upper
                        break;
                    }
                }
                sides[i] = s;
            }
        }
    }

    return sides;
}

} // namespace gismo
<|endoftext|>


<commit_before>#include <debug.hpp>

#include <newDishWindow.hpp>
#include "ui_newDishWindow.h"

NewDishWindow::NewDishWindow(QWidget *parent) :
    QDialog {parent},
    ui {new Ui::NewDishWindow},
    foodStringList {new QStringList},
    itemListModel {new QStringListModel {*foodStringList, NULL}} {

    ui->setupUi(this);

    ui->listView_1->setModel(itemListModel);

    ui->tableWidget_1->setColumnCount(2);

    PRINT_OBJ("NewDishWindow created");
}

NewDishWindow::~NewDishWindow() {
    delete ui;

    PRINT_OBJ("NewDishWindow destroyed");
}

void NewDishWindow::on_buttonBox_1_accepted() {
    emit itemObjectReady(createNewDish());

    this->hide();
}

void NewDishWindow::on_buttonBox_1_rejected() {
    this->hide();
}

void NewDishWindow::fillItemList(std::list<Item *> *itemsList) {
    avaliableItemsList = itemsList;

    for ( auto& entry: *itemsList ) {
        foodStringList->append(QString::fromStdString(entry->getName()));
    }

    itemListModel->setStringList(*foodStringList);
}

Dish* NewDishWindow::createNewDish(void) {
    return newDish;
}

void NewDishWindow::on_pushButton_1_clicked() {
    QModelIndexList selected = ui->listView_1->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() ) {
        std::list<Item *>::iterator item = avaliableItemsList->begin();

        std::advance(item, selected.first().row());

        if ( std::find(dishItemsList.begin(), dishItemsList.end(), *item) == dishItemsList.end() ) {
            QTableWidgetItem *newItem;
            dishItemsList.push_back(*item);

            newItem = new QTableWidgetItem(tr("%1").arg(QString::fromStdString((*item)->getName())));
            ui->tableWidget_1->setRowCount(ui->tableWidget_1->rowCount()+1);
            ui->tableWidget_1->setItem(ui->tableWidget_1->rowCount()-1, 0, newItem);
        }
   }
}

void NewDishWindow::on_pushButton_2_clicked() {

}
<commit_msg>newDishWindow: Reduce function call during ited adding<commit_after>#include <debug.hpp>

#include <newDishWindow.hpp>
#include "ui_newDishWindow.h"

NewDishWindow::NewDishWindow(QWidget *parent) :
    QDialog {parent},
    ui {new Ui::NewDishWindow},
    foodStringList {new QStringList},
    itemListModel {new QStringListModel {*foodStringList, NULL}} {

    ui->setupUi(this);

    ui->listView_1->setModel(itemListModel);

    ui->tableWidget_1->setColumnCount(2);

    PRINT_OBJ("NewDishWindow created");
}

NewDishWindow::~NewDishWindow() {
    delete ui;

    PRINT_OBJ("NewDishWindow destroyed");
}

void NewDishWindow::on_buttonBox_1_accepted() {
    emit itemObjectReady(createNewDish());

    this->hide();
}

void NewDishWindow::on_buttonBox_1_rejected() {
    this->hide();
}

void NewDishWindow::fillItemList(std::list<Item *> *itemsList) {
    avaliableItemsList = itemsList;

    for ( auto& entry: *itemsList ) {
        foodStringList->append(QString::fromStdString(entry->getName()));
    }

    itemListModel->setStringList(*foodStringList);
}

Dish* NewDishWindow::createNewDish(void) {
    return newDish;
}

void NewDishWindow::on_pushButton_1_clicked() {
    QModelIndexList selected = ui->listView_1->selectionModel()->selectedIndexes();

    if ( !selected.isEmpty() ) {
        std::list<Item *>::iterator item = avaliableItemsList->begin();

        std::advance(item, selected.first().row());

        if ( std::find(dishItemsList.begin(), dishItemsList.end(), *item) == dishItemsList.end() ) {
            QTableWidgetItem *newItem;
            int rowCount = ui->tableWidget_1->rowCount();

            dishItemsList.push_back(*item);

            newItem = new QTableWidgetItem(tr("%1").arg(QString::fromStdString((*item)->getName())));
            ui->tableWidget_1->setRowCount(rowCount+1);
            ui->tableWidget_1->setItem(rowCount, 0, newItem);
        }
   }
}

void NewDishWindow::on_pushButton_2_clicked() {

}
<|endoftext|>


<commit_before>/*
 * Copyright 2011, 2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thread>
#include <GL/freeglut.h>

#include "DOMImplementationImp.h"
#include "ECMAScript.h"
#include "WindowImp.h"
#include "font/FontDatabase.h"
#include "http/HTTPConnection.h"

#include "Test.util.h"

#ifdef USE_V8
#include "v8/ScriptV8.h"
#endif  // USE_V8

using namespace org::w3c::dom::bootstrap;
using namespace org::w3c::dom;

html::Window window(0);

int main(int argc, char* argv[])
{
#ifdef USE_V8
    v8::HandleScope handleScope;
#endif  // USE_V8

    if (argc < 3) {
        std::cout << "usage : " << argv[0] << " navigator_directory [user.css]\n";
        return EXIT_FAILURE;
    }

    init(&argc, argv);
    initLogLevel(&argc, argv);
    initFonts(&argc, argv);

    // Load the default CSS file
    std::string defaultSheet = argv[1];
    defaultSheet += "/default.css";
    getDOMImplementation()->setDefaultCSSStyleSheet(loadStyleSheet(defaultSheet.c_str()));

    // Load the user CSS file
    if (3 <= argc)
        getDOMImplementation()->setUserCSSStyleSheet(loadStyleSheet(argv[2]));

    std::thread httpService(std::ref(HttpConnectionManager::getInstance()));

    // Set privileges to the navigator window.
    char navigatorUrl[PATH_MAX + 7];
    strcpy(navigatorUrl, "file://");
    realpath(argv[1], navigatorUrl + 7);
    HttpRequest::setAboutPath(navigatorUrl + 7);
    strcat(navigatorUrl,  "/navigator.html");
    WindowImp* imp = new WindowImp();
    window = imp;
    imp->enableZoom(false);
    imp->open(utfconv(navigatorUrl), u"_self", u"", true);

    glutMainLoop();

    window = 0;

    ECMAScriptContext::shutDown();

    HttpConnectionManager::getInstance().stop();
    httpService.join();
}
<commit_msg>(main) : Fix a bug.<commit_after>/*
 * Copyright 2011, 2012 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thread>
#include <GL/freeglut.h>

#include "DOMImplementationImp.h"
#include "ECMAScript.h"
#include "WindowImp.h"
#include "font/FontDatabase.h"
#include "http/HTTPConnection.h"

#include "Test.util.h"

#ifdef USE_V8
#include "v8/ScriptV8.h"
#endif  // USE_V8

using namespace org::w3c::dom::bootstrap;
using namespace org::w3c::dom;

html::Window window(0);

int main(int argc, char* argv[])
{
#ifdef USE_V8
    v8::HandleScope handleScope;
#endif  // USE_V8

    if (argc < 2) {
        std::cout << "usage : " << argv[0] << " navigator_directory [user.css]\n";
        return EXIT_FAILURE;
    }

    init(&argc, argv);
    initLogLevel(&argc, argv);
    initFonts(&argc, argv);

    // Load the default CSS file
    std::string defaultSheet = argv[1];
    defaultSheet += "/default.css";
    getDOMImplementation()->setDefaultCSSStyleSheet(loadStyleSheet(defaultSheet.c_str()));

    // Load the user CSS file
    if (3 <= argc)
        getDOMImplementation()->setUserCSSStyleSheet(loadStyleSheet(argv[2]));

    std::thread httpService(std::ref(HttpConnectionManager::getInstance()));

    // Set privileges to the navigator window.
    char navigatorUrl[PATH_MAX + 7];
    strcpy(navigatorUrl, "file://");
    realpath(argv[1], navigatorUrl + 7);
    HttpRequest::setAboutPath(navigatorUrl + 7);
    strcat(navigatorUrl,  "/navigator.html");
    WindowImp* imp = new WindowImp();
    window = imp;
    imp->enableZoom(false);
    imp->open(utfconv(navigatorUrl), u"_self", u"", true);

    glutMainLoop();

    window = 0;

    ECMAScriptContext::shutDown();

    HttpConnectionManager::getInstance().stop();
    httpService.join();
}
<|endoftext|>