<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: testcontainer.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 09:32:23 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/
#include <osl/mutex.hxx>

#include <cppuhelper/interfacecontainer.hxx>
#include <cppuhelper/implbase1.hxx>

#include <com/sun/star/beans/XVetoableChangeListener.hpp>

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

class TestListener : public WeakImplHelper1< XVetoableChangeListener >
{
    // Methods
    virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException)
        {

        }

    virtual void SAL_CALL vetoableChange( const ::com::sun::star::beans::PropertyChangeEvent& aEvent )
       throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException)
        {

        }

};

void test_interfacecontainer()
{
    Mutex mutex;

    {
        OInterfaceContainerHelper helper( mutex );

        Reference< XVetoableChangeListener > r1 = new TestListener();
        Reference< XVetoableChangeListener > r2 = new TestListener();
        Reference< XVetoableChangeListener > r3 = new TestListener();

        helper.addInterface( r1 );
        helper.addInterface( r2 );
        helper.addInterface( r3 );

        helper.disposeAndClear( EventObject() );
    }

    {
        OInterfaceContainerHelper helper( mutex );

        Reference< XVetoableChangeListener > r1 = new TestListener();
        Reference< XVetoableChangeListener > r2 = new TestListener();
        Reference< XVetoableChangeListener > r3 = new TestListener();

        helper.addInterface( r1 );
        helper.addInterface( r2 );
        helper.addInterface( r3 );

        OInterfaceIteratorHelper iterator( helper );

        while( iterator.hasMoreElements() )
            ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );

        helper.disposeAndClear( EventObject() );
    }

    {
        OInterfaceContainerHelper helper( mutex );

        Reference< XVetoableChangeListener > r1 = new TestListener();
        Reference< XVetoableChangeListener > r2 = new TestListener();
        Reference< XVetoableChangeListener > r3 = new TestListener();

        helper.addInterface( r1 );
        helper.addInterface( r2 );
        helper.addInterface( r3 );

        OInterfaceIteratorHelper iterator( helper );

        ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
        iterator.remove();
        ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
        iterator.remove();
        ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
        iterator.remove();

        OSL_ASSERT( helper.getLength() == 0 );
        helper.disposeAndClear( EventObject() );
    }

    {
        OInterfaceContainerHelper helper( mutex );

        Reference< XVetoableChangeListener > r1 = new TestListener();
        Reference< XVetoableChangeListener > r2 = new TestListener();
        Reference< XVetoableChangeListener > r3 = new TestListener();

        helper.addInterface( r1 );
        helper.addInterface( r2 );
        helper.addInterface( r3 );

        {
            OInterfaceIteratorHelper iterator( helper );
            while( iterator.hasMoreElements() )
            {
                Reference< XVetoableChangeListener > r = ((XVetoableChangeListener*)iterator.next());
                if( r == r1 )
                    iterator.remove();
            }
        }
        OSL_ASSERT( helper.getLength() == 2 );
        {
            OInterfaceIteratorHelper iterator( helper );
            while( iterator.hasMoreElements() )
            {
                Reference< XVetoableChangeListener > r = ((XVetoableChangeListener*)iterator.next());
                OSL_ASSERT( r != r1 && ( r == r2 || r == r3 ) );
            }
        }

        helper.disposeAndClear( EventObject() );
    }
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.2.56); FILE MERGED 2006/09/01 17:23:19 kaib 1.2.56.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: testcontainer.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 12:44:03 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cppuhelper.hxx"
#include <osl/mutex.hxx>

#include <cppuhelper/interfacecontainer.hxx>
#include <cppuhelper/implbase1.hxx>

#include <com/sun/star/beans/XVetoableChangeListener.hpp>

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

class TestListener : public WeakImplHelper1< XVetoableChangeListener >
{
    // Methods
    virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException)
        {

        }

    virtual void SAL_CALL vetoableChange( const ::com::sun::star::beans::PropertyChangeEvent& aEvent )
       throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException)
        {

        }

};

void test_interfacecontainer()
{
    Mutex mutex;

    {
        OInterfaceContainerHelper helper( mutex );

        Reference< XVetoableChangeListener > r1 = new TestListener();
        Reference< XVetoableChangeListener > r2 = new TestListener();
        Reference< XVetoableChangeListener > r3 = new TestListener();

        helper.addInterface( r1 );
        helper.addInterface( r2 );
        helper.addInterface( r3 );

        helper.disposeAndClear( EventObject() );
    }

    {
        OInterfaceContainerHelper helper( mutex );

        Reference< XVetoableChangeListener > r1 = new TestListener();
        Reference< XVetoableChangeListener > r2 = new TestListener();
        Reference< XVetoableChangeListener > r3 = new TestListener();

        helper.addInterface( r1 );
        helper.addInterface( r2 );
        helper.addInterface( r3 );

        OInterfaceIteratorHelper iterator( helper );

        while( iterator.hasMoreElements() )
            ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );

        helper.disposeAndClear( EventObject() );
    }

    {
        OInterfaceContainerHelper helper( mutex );

        Reference< XVetoableChangeListener > r1 = new TestListener();
        Reference< XVetoableChangeListener > r2 = new TestListener();
        Reference< XVetoableChangeListener > r3 = new TestListener();

        helper.addInterface( r1 );
        helper.addInterface( r2 );
        helper.addInterface( r3 );

        OInterfaceIteratorHelper iterator( helper );

        ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
        iterator.remove();
        ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
        iterator.remove();
        ((XVetoableChangeListener*)iterator.next())->vetoableChange( PropertyChangeEvent() );
        iterator.remove();

        OSL_ASSERT( helper.getLength() == 0 );
        helper.disposeAndClear( EventObject() );
    }

    {
        OInterfaceContainerHelper helper( mutex );

        Reference< XVetoableChangeListener > r1 = new TestListener();
        Reference< XVetoableChangeListener > r2 = new TestListener();
        Reference< XVetoableChangeListener > r3 = new TestListener();

        helper.addInterface( r1 );
        helper.addInterface( r2 );
        helper.addInterface( r3 );

        {
            OInterfaceIteratorHelper iterator( helper );
            while( iterator.hasMoreElements() )
            {
                Reference< XVetoableChangeListener > r = ((XVetoableChangeListener*)iterator.next());
                if( r == r1 )
                    iterator.remove();
            }
        }
        OSL_ASSERT( helper.getLength() == 2 );
        {
            OInterfaceIteratorHelper iterator( helper );
            while( iterator.hasMoreElements() )
            {
                Reference< XVetoableChangeListener > r = ((XVetoableChangeListener*)iterator.next());
                OSL_ASSERT( r != r1 && ( r == r2 || r == r3 ) );
            }
        }

        helper.disposeAndClear( EventObject() );
    }
}
<|endoftext|>


<commit_before>// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

#include <cstdlib>

#include <string>
#include <sstream>
#include <iterator>

//#define DODS_DEBUG

#include "D4FunctionScanner.h"
#include "D4FunctionDriver.h"
#include "d4_function_parser.tab.hh"
#include "DMR.h"
#include "D4RValue.h"

#include "BaseType.h"

#include "escaping.h"
#include "debug.h"

namespace libdap {

bool D4FunctionDriver::parse(const std::string &expr)
{
	d_expr = expr;	// set for error messages. See the %initial-action section of .yy

	std::istringstream iss(expr);
	D4FunctionScanner *scanner = new D4FunctionScanner(iss);

	D4FunctionParser *parser = new D4FunctionParser(*scanner, *this /* driver */);

	if (trace_parsing()) {
		parser->set_debug_level(1);
		parser->set_debug_stream(std::cerr);
	}

	return parser->parse() == 0;
}

/**
 * Build and return a new RValue. Allocates the new D4RValue object.
 * The code tries first to find the id in the DMR - that is, it checks
 * first to see if it is a variable in the current dataset. If that
 * fails it will try to build an unsigned long long, a long long or
 * a double from the string (in that order). If that fails the code
 * converts the id into a string.
 *
 * @param id An identifier (really a string) parsed from the function
 * expression. May contain quotes.
 * @return Return a pointer to the new allocated D4RValue object.
 */
D4RValue *
D4FunctionDriver::build_rvalue(const std::string &id)
{
    BaseType *btp = 0;

    // Look for the id in the dataset first
    if (top_basetype()) {
        btp = top_basetype()->var(id);
    }
    else {
        btp = dmr()->root()->find_var(id);
    }

    if (btp)
        return new D4RValue(btp);

    // If the id is not a variable, try to turn it into a constant,
    // otherwise, its an error.
    char *end_ptr = 0;

    errno = 0;
    unsigned long long ull_val = strtoull(id.c_str(), &end_ptr, 0);
    if (end_ptr == '\0' && errno == 0)
    	return new D4RValue(ull_val);

    errno = 0;
    long long ll_val = strtoll(id.c_str(), &end_ptr, 0);
    if (end_ptr == '\0' && errno == 0)
    	return new D4RValue(ll_val);

    errno = 0;
    double d_val = strtod(id.c_str(), &end_ptr);
    if (end_ptr == '\0' && errno == 0)
    	return new D4RValue(d_val);

    return new D4RValue(www2id(id));
}

void
D4FunctionDriver::throw_not_found(const string &id, const string &ident)
{
    throw Error(d_expr + ": The variable " + id + " was not found in the dataset (" + ident + ").");
}

void
D4FunctionDriver::throw_not_array(const string &id, const string &ident)
{
	throw Error(d_expr + ": The variable '" + id + "' is not an Array variable (" + ident + ").");
}

// This method is called from the parser (see d4_ce_parser.yy, down in the code
// section). This will be called during the call to D4FunctionParser::parse(), that
// is inside D4FunctionDriver::parse(...)
void
D4FunctionDriver::error(const libdap::location &l, const std::string &m)
{
	std::cerr << l << ": " << m << std::endl;
}

#if 0
void
D4CEDriver::set_array_slices(const std::string &id, Array *a)
{
    // Test that the indexes and dimensions match in number
    if (d_indexes.size() != a->dimensions())
        throw Error("The index constraint for '" + id + "' does not match its rank.");

    Array::Dim_iter d = a->dim_begin();
    for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) {
        if ((*i).stride > (unsigned long long)a->dimension_stop(d, false))
            throw Error("For '" + id + "', the index stride value is greater than the number of elements in the Array");
        if (!(*i).rest && ((*i).stop) > (unsigned long long)a->dimension_stop(d, false))
            throw Error("For '" + id + "', the index stop value is greater than the number of elements in the Array");

        D4Dimension *dim = a->dimension_D4dim(d);

        // In a DAP4 CE, specifying '[]' as an array dimension slice has two meanings.
        // It can mean 'all the elements' of the dimension or 'apply the slicing inherited
        // from the shared dimension'. The latter might be provide 'all the elements'
        // but regardless, the Array object must record the CE correctly.

        if (dim && (*i).empty) {
            a->add_constraint(d, dim);
        }
        else {
            a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
        }

        ++d;
    }

    d_indexes.clear();
}
#endif
#if 0
void
D4CEDriver::search_for_and_mark_arrays(BaseType *btp)
{
	DBG(cerr << "Entering D4CEDriver::search_for_and_mark_arrays...(" << btp->name() << ")" << endl);

	assert(btp->is_constructor_type());

	Constructor *ctor = static_cast<Constructor*>(btp);
	for (Constructor::Vars_iter i = ctor->var_begin(), e = ctor->var_end(); i != e; ++i) {
		switch ((*i)->type()) {
		case dods_array_c:
			DBG(cerr << "Found an array: " << (*i)->name() << endl);
			mark_array_variable(*i);
			break;
		case dods_structure_c:
		case dods_sequence_c:
			DBG(cerr << "Found a ctor: " << (*i)->name() << endl);
			search_for_and_mark_arrays(*i);
			break;
		default:
			break;
		}
	}
}

/**
 * When an identifier is used in a CE, is becomes part of the 'current projection,'
 * which means it is part of the set of variable to be sent back to the client. This
 * method sets a flag in the variable (send_p: send predicate) indicating that.
 *
 * @note This will check if the variable is an array and set it's slices accordingly
 * @param btp BaseType pointer to the variable. Must be non-null
 * @return The BaseType* to the variable; the send_p flag is set as a side effect.
 */
BaseType *
D4CEDriver::mark_variable(BaseType *btp)
{
    assert(btp);

    DBG(cerr << "In D4CEDriver::mark_variable... (" << btp->name() << "; " << btp->type_name() << ")" << endl);

    btp->set_send_p(true);

    if (btp->type() == dods_array_c ) {
    	mark_array_variable(btp);
    }

    // Test for Constructors and marks arrays they contain
	if (btp->is_constructor_type()) {
		search_for_and_mark_arrays(btp);
	}
	else if (btp->type() == dods_array_c && btp->var() && btp->var()->is_constructor_type()) {
		search_for_and_mark_arrays(btp->var());
	}

    // Now set the parent variables
    BaseType *parent = btp->get_parent();
    while (parent) {
        parent->BaseType::set_send_p(true); // Just set the parent using BaseType's impl.
        parent = parent->get_parent();
    }

    return btp;
}

/**
 * Add an array to the current projection with slicing. Calling this method will result
 * in the array being returned with anonymous dimensions.
 *
 * @note If id is an array that has shared dimensions and uses '[]' where a shared dimension
 * is found and if that shared dimension has been sliced, then the slice is used as the array's
 * slice for that dimension (there must be an easier way to explain that...)
 *
 * @param id
 * @return The BaseType* to the Array variable; the send_p and slicing information is
 * set as a side effect.
 */
BaseType *
D4CEDriver::mark_array_variable(BaseType *btp)
{
	assert(btp->type() == dods_array_c);

	Array *a = static_cast<Array*>(btp);

	// If an array appears in a CE without the slicing operators ([]) we still have to
	// call set_user_by_projected_var(true) for all of it's sdims for them to appear in
	// the CDMR.
	if (d_indexes.empty()) {
	    for (Array::Dim_iter d = a->dim_begin(), de = a->dim_end(); d != de; ++d) {
	        D4Dimension *dim = a->dimension_D4dim(d);
	        if (dim) {
	        	a->add_constraint(d, dim);
	        }
	    }
	}
    else {
        // Test that the indexes and dimensions match in number
        if (d_indexes.size() != a->dimensions())
            throw Error("The index constraint for '" + btp->name() + "' does not match its rank.");

        Array::Dim_iter d = a->dim_begin();
        for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) {
            if ((*i).stride > (unsigned long long) a->dimension_stop(d, false))
                throw Error(
                        "For '" + btp->name()
                                + "', the index stride value is greater than the number of elements in the Array");
            if (!(*i).rest && ((*i).stop) > (unsigned long long) a->dimension_stop(d, false))
                throw Error(
                        "For '" + btp->name()
                                + "', the index stop value is greater than the number of elements in the Array");

            D4Dimension *dim = a->dimension_D4dim(d);

            // In a DAP4 CE, specifying '[]' as an array dimension slice has two meanings.
            // It can mean 'all the elements' of the dimension or 'apply the slicing inherited
            // from the shared dimension'. The latter might be provide 'all the elements'
            // but regardless, the Array object must record the CE correctly.

            if (dim && (*i).empty) {
                a->add_constraint(d, dim);  // calls set_used_by_projected_var(true) + more
            }
            else {
                a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
            }

            ++d;
        }

        d_indexes.clear();
    }

	return btp;
}

/**
 * Add an array to the current projection with slicing. Calling this method will result
 * in the array being returned with anonymous dimensions.
 * @param id
 * @return The BaseType* to the Array variable; the send_p and slicing information is
 * set as a side effect.
 */
D4Dimension *
D4CEDriver::slice_dimension(const std::string &id, const index &i)
{
    D4Dimension *dim = dmr()->root()->find_dim(id);

    if (i.stride > dim->size())
        throw Error("For '" + id + "', the index stride value is greater than the size of the dimension");
    if (!i.rest && (i.stop > dim->size() - 1))
        throw Error("For '" + id + "', the index stop value is greater than the size of the dimension");

    dim->set_constraint(i.start, i.stride, i.rest ? dim->size() - 1: i.stop);

    return dim;
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i)
{
	unsigned long long v = get_ull(i.c_str());
	return index(v, 1, v, false, false /*empty*/);
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i, const std::string &s, const std::string &e)
{
	return index(get_ull(i.c_str()), get_ull(s.c_str()), get_ull(e.c_str()), false, false /*empty*/);
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i, unsigned long long s, const std::string &e)
{
	return index(get_ull(i.c_str()), s, get_ull(e.c_str()), false, false /*empty*/);
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i, const std::string &s)
{
	return index(get_ull(i.c_str()), get_ull(s.c_str()), 0, true, false /*empty*/);
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i, unsigned long long s)
{
	return index(get_ull(i.c_str()), s, 0, true, false /*empty*/);
}
#endif

} /* namespace libdap */
<commit_msg>lobdap: Fixed compile issue<commit_after>// -*- mode: c++; c-basic-offset:4 -*-

// This file is part of libdap, A C++ implementation of the OPeNDAP Data
// Access Protocol.

// Copyright (c) 2002,2003 OPeNDAP, Inc.
// Author: James Gallagher <jgallagher@opendap.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.

#include <cstdlib>
#include <cerrno>

#include <string>
#include <sstream>
#include <iterator>

//#define DODS_DEBUG

#include "D4FunctionScanner.h"
#include "D4FunctionDriver.h"
#include "d4_function_parser.tab.hh"
#include "DMR.h"
#include "D4RValue.h"

#include "BaseType.h"

#include "escaping.h"
#include "debug.h"

namespace libdap {

bool D4FunctionDriver::parse(const std::string &expr)
{
	d_expr = expr;	// set for error messages. See the %initial-action section of .yy

	std::istringstream iss(expr);
	D4FunctionScanner *scanner = new D4FunctionScanner(iss);

	D4FunctionParser *parser = new D4FunctionParser(*scanner, *this /* driver */);

	if (trace_parsing()) {
		parser->set_debug_level(1);
		parser->set_debug_stream(std::cerr);
	}

	return parser->parse() == 0;
}

/**
 * Build and return a new RValue. Allocates the new D4RValue object.
 * The code tries first to find the id in the DMR - that is, it checks
 * first to see if it is a variable in the current dataset. If that
 * fails it will try to build an unsigned long long, a long long or
 * a double from the string (in that order). If that fails the code
 * converts the id into a string.
 *
 * @param id An identifier (really a string) parsed from the function
 * expression. May contain quotes.
 * @return Return a pointer to the new allocated D4RValue object.
 */
D4RValue *
D4FunctionDriver::build_rvalue(const std::string &id)
{
    BaseType *btp = 0;

    // Look for the id in the dataset first
    if (top_basetype()) {
        btp = top_basetype()->var(id);
    }
    else {
        btp = dmr()->root()->find_var(id);
    }

    if (btp)
        return new D4RValue(btp);

    // If the id is not a variable, try to turn it into a constant,
    // otherwise, its an error.
    char *end_ptr = 0;

    errno = 0;
    unsigned long long ull_val = strtoull(id.c_str(), &end_ptr, 0);
    if (end_ptr == '\0' && errno == 0)
    	return new D4RValue(ull_val);

    errno = 0;
    long long ll_val = strtoll(id.c_str(), &end_ptr, 0);
    if (end_ptr == '\0' && errno == 0)
    	return new D4RValue(ll_val);

    errno = 0;
    double d_val = strtod(id.c_str(), &end_ptr);
    if (end_ptr == '\0' && errno == 0)
    	return new D4RValue(d_val);

    return new D4RValue(www2id(id));
}

void
D4FunctionDriver::throw_not_found(const string &id, const string &ident)
{
    throw Error(d_expr + ": The variable " + id + " was not found in the dataset (" + ident + ").");
}

void
D4FunctionDriver::throw_not_array(const string &id, const string &ident)
{
	throw Error(d_expr + ": The variable '" + id + "' is not an Array variable (" + ident + ").");
}

// This method is called from the parser (see d4_ce_parser.yy, down in the code
// section). This will be called during the call to D4FunctionParser::parse(), that
// is inside D4FunctionDriver::parse(...)
void
D4FunctionDriver::error(const libdap::location &l, const std::string &m)
{
	std::cerr << l << ": " << m << std::endl;
}

#if 0
void
D4CEDriver::set_array_slices(const std::string &id, Array *a)
{
    // Test that the indexes and dimensions match in number
    if (d_indexes.size() != a->dimensions())
        throw Error("The index constraint for '" + id + "' does not match its rank.");

    Array::Dim_iter d = a->dim_begin();
    for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) {
        if ((*i).stride > (unsigned long long)a->dimension_stop(d, false))
            throw Error("For '" + id + "', the index stride value is greater than the number of elements in the Array");
        if (!(*i).rest && ((*i).stop) > (unsigned long long)a->dimension_stop(d, false))
            throw Error("For '" + id + "', the index stop value is greater than the number of elements in the Array");

        D4Dimension *dim = a->dimension_D4dim(d);

        // In a DAP4 CE, specifying '[]' as an array dimension slice has two meanings.
        // It can mean 'all the elements' of the dimension or 'apply the slicing inherited
        // from the shared dimension'. The latter might be provide 'all the elements'
        // but regardless, the Array object must record the CE correctly.

        if (dim && (*i).empty) {
            a->add_constraint(d, dim);
        }
        else {
            a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
        }

        ++d;
    }

    d_indexes.clear();
}
#endif
#if 0
void
D4CEDriver::search_for_and_mark_arrays(BaseType *btp)
{
	DBG(cerr << "Entering D4CEDriver::search_for_and_mark_arrays...(" << btp->name() << ")" << endl);

	assert(btp->is_constructor_type());

	Constructor *ctor = static_cast<Constructor*>(btp);
	for (Constructor::Vars_iter i = ctor->var_begin(), e = ctor->var_end(); i != e; ++i) {
		switch ((*i)->type()) {
		case dods_array_c:
			DBG(cerr << "Found an array: " << (*i)->name() << endl);
			mark_array_variable(*i);
			break;
		case dods_structure_c:
		case dods_sequence_c:
			DBG(cerr << "Found a ctor: " << (*i)->name() << endl);
			search_for_and_mark_arrays(*i);
			break;
		default:
			break;
		}
	}
}

/**
 * When an identifier is used in a CE, is becomes part of the 'current projection,'
 * which means it is part of the set of variable to be sent back to the client. This
 * method sets a flag in the variable (send_p: send predicate) indicating that.
 *
 * @note This will check if the variable is an array and set it's slices accordingly
 * @param btp BaseType pointer to the variable. Must be non-null
 * @return The BaseType* to the variable; the send_p flag is set as a side effect.
 */
BaseType *
D4CEDriver::mark_variable(BaseType *btp)
{
    assert(btp);

    DBG(cerr << "In D4CEDriver::mark_variable... (" << btp->name() << "; " << btp->type_name() << ")" << endl);

    btp->set_send_p(true);

    if (btp->type() == dods_array_c ) {
    	mark_array_variable(btp);
    }

    // Test for Constructors and marks arrays they contain
	if (btp->is_constructor_type()) {
		search_for_and_mark_arrays(btp);
	}
	else if (btp->type() == dods_array_c && btp->var() && btp->var()->is_constructor_type()) {
		search_for_and_mark_arrays(btp->var());
	}

    // Now set the parent variables
    BaseType *parent = btp->get_parent();
    while (parent) {
        parent->BaseType::set_send_p(true); // Just set the parent using BaseType's impl.
        parent = parent->get_parent();
    }

    return btp;
}

/**
 * Add an array to the current projection with slicing. Calling this method will result
 * in the array being returned with anonymous dimensions.
 *
 * @note If id is an array that has shared dimensions and uses '[]' where a shared dimension
 * is found and if that shared dimension has been sliced, then the slice is used as the array's
 * slice for that dimension (there must be an easier way to explain that...)
 *
 * @param id
 * @return The BaseType* to the Array variable; the send_p and slicing information is
 * set as a side effect.
 */
BaseType *
D4CEDriver::mark_array_variable(BaseType *btp)
{
	assert(btp->type() == dods_array_c);

	Array *a = static_cast<Array*>(btp);

	// If an array appears in a CE without the slicing operators ([]) we still have to
	// call set_user_by_projected_var(true) for all of it's sdims for them to appear in
	// the CDMR.
	if (d_indexes.empty()) {
	    for (Array::Dim_iter d = a->dim_begin(), de = a->dim_end(); d != de; ++d) {
	        D4Dimension *dim = a->dimension_D4dim(d);
	        if (dim) {
	        	a->add_constraint(d, dim);
	        }
	    }
	}
    else {
        // Test that the indexes and dimensions match in number
        if (d_indexes.size() != a->dimensions())
            throw Error("The index constraint for '" + btp->name() + "' does not match its rank.");

        Array::Dim_iter d = a->dim_begin();
        for (vector<index>::iterator i = d_indexes.begin(), e = d_indexes.end(); i != e; ++i) {
            if ((*i).stride > (unsigned long long) a->dimension_stop(d, false))
                throw Error(
                        "For '" + btp->name()
                                + "', the index stride value is greater than the number of elements in the Array");
            if (!(*i).rest && ((*i).stop) > (unsigned long long) a->dimension_stop(d, false))
                throw Error(
                        "For '" + btp->name()
                                + "', the index stop value is greater than the number of elements in the Array");

            D4Dimension *dim = a->dimension_D4dim(d);

            // In a DAP4 CE, specifying '[]' as an array dimension slice has two meanings.
            // It can mean 'all the elements' of the dimension or 'apply the slicing inherited
            // from the shared dimension'. The latter might be provide 'all the elements'
            // but regardless, the Array object must record the CE correctly.

            if (dim && (*i).empty) {
                a->add_constraint(d, dim);  // calls set_used_by_projected_var(true) + more
            }
            else {
                a->add_constraint(d, (*i).start, (*i).stride, (*i).rest ? -1 : (*i).stop);
            }

            ++d;
        }

        d_indexes.clear();
    }

	return btp;
}

/**
 * Add an array to the current projection with slicing. Calling this method will result
 * in the array being returned with anonymous dimensions.
 * @param id
 * @return The BaseType* to the Array variable; the send_p and slicing information is
 * set as a side effect.
 */
D4Dimension *
D4CEDriver::slice_dimension(const std::string &id, const index &i)
{
    D4Dimension *dim = dmr()->root()->find_dim(id);

    if (i.stride > dim->size())
        throw Error("For '" + id + "', the index stride value is greater than the size of the dimension");
    if (!i.rest && (i.stop > dim->size() - 1))
        throw Error("For '" + id + "', the index stop value is greater than the size of the dimension");

    dim->set_constraint(i.start, i.stride, i.rest ? dim->size() - 1: i.stop);

    return dim;
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i)
{
	unsigned long long v = get_ull(i.c_str());
	return index(v, 1, v, false, false /*empty*/);
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i, const std::string &s, const std::string &e)
{
	return index(get_ull(i.c_str()), get_ull(s.c_str()), get_ull(e.c_str()), false, false /*empty*/);
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i, unsigned long long s, const std::string &e)
{
	return index(get_ull(i.c_str()), s, get_ull(e.c_str()), false, false /*empty*/);
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i, const std::string &s)
{
	return index(get_ull(i.c_str()), get_ull(s.c_str()), 0, true, false /*empty*/);
}

D4CEDriver::index
D4CEDriver::make_index(const std::string &i, unsigned long long s)
{
	return index(get_ull(i.c_str()), s, 0, true, false /*empty*/);
}
#endif

} /* namespace libdap */
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "CityGen.h"
#include "Structure.h"
#include "Rect.h"
#include "Utilities.h"
#include "SavableCityData.h"

#include "BaseFrame.h"
#include "ActorSystem.h"
#include "ActorAids.h"
//the size of each city
const int citysize = 150;

//the space between each city
const int cityspacing = 250;

int CityGen::BufferIndex(GameTile* tile,int x, int y) {
	return 4 * (y*TILE_SIZE + x);
}

void CityGen::construct_road(GameTile* tile, vec3 start, vec3 end){

}
void CityGen::construct_building(GameTile* tile, vec3 pos){
	//BEGIN BUILDING DEMO
	//Load building floors (note lack of extension)
	Structure * bottomFloor = Structure::LoadStructure("teststructures/testfloor30x10");
	Structure * transitionFloor = Structure::LoadStructure("teststructures/testfloor30x10to20x10");
	Structure * topFloor = Structure::LoadStructure("teststructures/testfloor20x10");

	//Randomize the number of floors a bit
	//Obviously more varied randomization would have to be done
	//for more variation in buildings
	int numberOfBaseFloors = rand() % 3;
	int numberOfTopFloors = rand() % 3;

	//A Building is used to construct a structure by stacking other structures (floors) together
	Building newBuilding;

	//Stack bottom floors
	for (int i = 0; i < numberOfTopFloors; i++)
		newBuilding.Stack(bottomFloor);

	//Add an adapter floor
	newBuilding.Stack(transitionFloor);

	//Add the rest
	for (int i = 0; i < numberOfTopFloors; i++)
		newBuilding.Stack(topFloor);

	//At this point some sort of roof should have been added
	//but I didn't make one

	//When you're all done stacking floors
	//call construct once to internally prepare the structure
	//for use
	newBuilding.ConstructStructure();

	//Then call PlaceStructure one or more times to place the structure
	//in whatever 2d positions you want
	//automatically compensates for terrain (no building voxels underneath the ground)
	newBuilding.PlaceStructure(tile,vec2(pos.x,pos.y));

}

void CityGen::construct_city(GameTile * tile, vec3 pos) {
	//First create city points at even intervals
	const static float evenBuildingDistance = 20.0f;
	const static float buildingSize = 15.0f;

	ContiguousList<Rect> buildingPlacements;

	TileCell * cells = tile->Cells;

	vec3 tileOffset = vec3(tile->tile_x,tile->tile_y,0) * vec3(TILE_SIZE,TILE_SIZE,1.0);

	//Warning HACK
	//create savable city data here
	SavableCityData * cityData = new SavableCityData();
	cityData->cityPosition = pos+tileOffset;
	cityData->ownedByPlayer = false;

	float originalCityHeight = cells[int((pos.y)*TILE_SIZE + pos.x)].height;

	//Generate lines
	//set<vec2> usedSpace;
	static const int lineCount = 30;
	static const int turretSkip = 6;
	static const int samples = 200;
	static const float anglePart = M_PI*2.0f/(float)lineCount;
	for (int p = 0; p < lineCount; p++) {
		vec2 lineDirection = glm::normalize(vec2(cos(anglePart*p),sin(anglePart*p)));
		float lineLength = citysize*1.5;
		float lineSection = lineLength/samples;

		if ((p % turretSkip) == 0) {
			//Place turret
			vec2 spos = glm::floor(lineDirection*(-lineLength/2.0f+samples/4*lineSection)) + vec2(pos);

			//raise the height around the turrent
			float newHeight = originalCityHeight +10.0f;
			for (int x = -1; x <= 0; x++) {
				for (int y = -1; y <= 0; y++) {
					vec2 absPos = spos+vec2(x,y);
					TileCell & cell = cells[int((absPos.y)*TILE_SIZE + absPos.x)];
					cell.height = newHeight;
				}
			}

			cityData->gunAlive.push_back(true);
			cityData->gunPositions.push_back(tileOffset+vec3(spos,newHeight));
		}

		//Generate the line by sampling along it

		for (int i = 0; i < samples; i++) {
			//Find the position
			vec2 spos = lineDirection*(-lineLength/2.0f+i*lineSection);
			spos = glm::floor(spos);
			//check that the position is within city limits
			if ((spos.x < -citysize/2.0) || (spos.y < -citysize/2.0))
				continue;
			if ((spos.x > citysize/2.0) || (spos.y > citysize/2.0))
				continue;
			//check that the position isn't too close to the center
			float len = glm::length(spos);
			if (len < 16)
				continue;
			//Place a line here
			float height = (len*len-15*15)*.0008+2;
			vec2 absPos = glm::floor(vec2(pos)+spos);
			TileCell & cell = cells[int((absPos.y)*TILE_SIZE + absPos.x)];
			cell.height += height;
			//City is stronger than surrounding terrain
			cell.cellHealth = 25;
			cell.cellMaxHealth = 25;
		}
	}

	//Different heights in the spire
	int ringHeights[5] = {
		30,
		28,
		24,
		18,
		10
	};

	//Place the spire
	for (float x = -4; x <= 4; x++) {
		for (float y = -4; y <= 4; y++) {
			float ring = max(abs(x),abs(y));
			vec2 spos = vec2(x,y)+vec2(pos);
			TileCell & cell = cells[int((spos.y)*TILE_SIZE + spos.x)];
			cell.height += ringHeights[(int)ring]*3/2;
			//The tower is made of tough stuff
			cell.cellHealth = 50;
			cell.cellMaxHealth = 50;
			//Register the center
			if (ring == 0) {
				cityData->cityCenterVoxel = spos+vec2(tileOffset);
				cityData->originalCityCenterVoxel = cell.height;
			}

		}
	}

	//flatten terrain
	//generate roads

	for (int y = -citysize / 2; y < citysize / 2; y++) {
		for (int x = -citysize / 2; x < citysize / 2; x++) {
			cells[int((pos.y + y)*TILE_SIZE + pos.x + x)].materialId = 2;
		}
	}

	//Super hack, transfer city data to ai
	Game()->Actors.Aids()->RegisterNewCity(cityData);

}

void CityGen::generatecitylocations(GameTile* tile){

	//the amount to blur
	const int blur = 4;

	//analyze the terrain
	//We Differentiate the terrain and then blur it 4x to achieve the effect of inteligent city placement

	//this will store the differential blur of the terrain
	float * analysis = new float[TILE_SIZE*TILE_SIZE];

	//This allows us to access the terrain values
	TileCell * cells = tile->Cells;

	//our operator ignores edges, so set them to be really high
	//This also helps keep cities off the edge of tiles because that breaks things
	for (int y = 0; y < TILE_SIZE; y++) {
		//left
		analysis[y*TILE_SIZE + 0] = 500;
		//right
		analysis[y*TILE_SIZE + TILE_SIZE - 1] = 500;
	}
	//check the x edge and normalize the height so it matches
	for (int x = 0; x < TILE_SIZE; x++) {
		//top
		analysis[0 * TILE_SIZE + x] = 500;
		//bottom
		analysis[(TILE_SIZE - 1)*TILE_SIZE + x] = 500;
	}

	//Get the slope using the Sobel Operator
	for (int y = 1; y < TILE_SIZE - 1; y++) {
		for (int x = 1; x < TILE_SIZE - 1; x++) {
			//directions don't actually matter, we just care about magnitude of change
			float bottomLeftIntensity = cells[TILE_SIZE*(y - 1) + x - 1].height;
			float topRightIntensity = cells[TILE_SIZE*(y + 1) + x + 1].height;
			float topLeftIntensity = cells[TILE_SIZE*(y + 1) + x - 1].height;
			float bottomRightIntensity = cells[TILE_SIZE*(y - 1) + x + 1].height;
			float leftIntensity = cells[TILE_SIZE*(y)+x - 1].height;
			float rightIntensity = cells[TILE_SIZE*(y)+x + 1].height;
			float bottomIntensity = cells[TILE_SIZE*(y - 1) + x].height;
			float topIntensity = cells[TILE_SIZE*(y + 1) + x].height;

			float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
			float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;

			float mag = glm::length(vec2(h, v));
			analysis[y*TILE_SIZE + x] = mag;
		}
	}

	//Apply Blur 4x
	for (int i = 0; i < blur; i++) {
		for (int y = 1; y < TILE_SIZE - 1; y++) {
			for (int x = 1; x < TILE_SIZE - 1; x++) {
				//directions don't actually matter, we just care about magnitude of change

				float bottomLeftIntensity = analysis[TILE_SIZE*(y - 1) + x - 1];
				float topRightIntensity = analysis[TILE_SIZE*(y + 1) + x + 1];
				float topLeftIntensity = analysis[TILE_SIZE*(y + 1) + x - 1];
				float bottomRightIntensity = analysis[TILE_SIZE*(y - 1) + x + 1];
				float leftIntensity = analysis[TILE_SIZE*(y)+x - 1];
				float rightIntensity = analysis[TILE_SIZE*(y)+x + 1];
				float bottomIntensity = analysis[TILE_SIZE*(y - 1) + x];
				float topIntensity = analysis[TILE_SIZE*(y + 1) + x];

				double top = topIntensity + topLeftIntensity + topRightIntensity;
				double middle = analysis[y*TILE_SIZE + x] + leftIntensity + rightIntensity;
				double bottom = bottomIntensity + bottomLeftIntensity + bottomRightIntensity;

				float average = (top + middle + bottom) / 9;

				analysis[y*TILE_SIZE + x] = average;
			}
		}
	}
	float minheight = 5000;
	vec3 citylocation;

	float noisetolerance = 3;
	float heighttolerance = 5;
	//figure out where to put the city but make sure it doesn't go off the edge
	for (int y = citysize/2+10; y < TILE_SIZE - (citysize/2+10); y++) {
		for (int x = citysize/2+10; x < TILE_SIZE - (citysize/2+10); x++) {
			if (analysis[y*TILE_SIZE + x] < noisetolerance) {

				//check if we're too close to another city
				bool tooclose = false;
				for (int i = 0; i < tile->Cities.size(); i++) {
					if (glm::length(vec2(tile->Cities[i].x - x, tile->Cities[i].y - y)) < cityspacing)
						tooclose = true;
				}

				if (!tooclose) {
					if (abs(cells[(y - citysize / 2)*TILE_SIZE + x - citysize / 2].height - cells[(y + citysize / 2)*TILE_SIZE + x - citysize / 2].height) < heighttolerance &&
						abs(cells[(y - citysize / 2)*TILE_SIZE + x + citysize / 2].height - cells[(y + citysize / 2)*TILE_SIZE + x + citysize / 2].height) < heighttolerance &&
						abs(cells[(y + citysize / 2)*TILE_SIZE + x + citysize / 2].height - cells[(y + citysize / 2)*TILE_SIZE + x - citysize / 2].height) < heighttolerance &&
						abs(cells[(y - citysize / 2)*TILE_SIZE + x + citysize / 2].height - cells[(y - citysize / 2)*TILE_SIZE + x - citysize / 2].height) < heighttolerance
						) {
						//make some cities
						tile->Cities.push_back(vec3(x, y, 0));
						cout << "CITY PLACED AT:" << x << " , " << y << endl;
					}
				}
			}
		}
	}

	//Flatten Terrain
	for (int i = 0; i < tile->Cities.size(); i++) {
		vec3 pos = tile->Cities[i];
		for (int y = -citysize / 2; y < citysize / 2; y++) {
			for (int x = -citysize / 2; x < citysize / 2; x++) {
				cells[int((pos.y + y)*TILE_SIZE + pos.x + x)].height = cells[int((pos.y)*TILE_SIZE + pos.x)].height;
			}
		}
	}

	// TODO : Blur city edges

	/*
	for (int i = 0; i < tile->Cities.size(); i++) {
		vec3 pos = tile->Cities[i];
		//walk along the edge, for each edge walk outward and normalize
		for (int y = pos.y - citysize/2; y < pos.y + citysize/2; y++) {
			//left
			analysis[y*TILE_SIZE + TILE_SIZE - 1] = 500;

			//right
			analysis[y*TILE_SIZE + TILE_SIZE - 1] = 500;
		}
		for (int x = pos.x - citysize / 2; x < pos.x + citysize / 2; x++) {
			//top
			analysis[0 * TILE_SIZE + x] = 500;
			//bottom
			analysis[(TILE_SIZE - 1)*TILE_SIZE + x] = 500;
		}
	}
	*/
	delete [] analysis;
}
void CityGen::GenerateCities(GameTile * tile) {
	generatecitylocations(tile);
	for (int i = 0; i < tile->Cities.size(); i++) {
		construct_city(tile, tile->Cities[i]);
	}
	tile->UpdateTileSection(0, 0, TILE_SIZE, TILE_SIZE);
}
<commit_msg>changed spire color<commit_after>#include "stdafx.h"
#include "CityGen.h"
#include "Structure.h"
#include "Rect.h"
#include "Utilities.h"
#include "SavableCityData.h"

#include "BaseFrame.h"
#include "ActorSystem.h"
#include "ActorAids.h"
//the size of each city
const int citysize = 150;

//the space between each city
const int cityspacing = 250;

int CityGen::BufferIndex(GameTile* tile,int x, int y) {
	return 4 * (y*TILE_SIZE + x);
}

void CityGen::construct_road(GameTile* tile, vec3 start, vec3 end){

}
void CityGen::construct_building(GameTile* tile, vec3 pos){
	//BEGIN BUILDING DEMO
	//Load building floors (note lack of extension)
	Structure * bottomFloor = Structure::LoadStructure("teststructures/testfloor30x10");
	Structure * transitionFloor = Structure::LoadStructure("teststructures/testfloor30x10to20x10");
	Structure * topFloor = Structure::LoadStructure("teststructures/testfloor20x10");

	//Randomize the number of floors a bit
	//Obviously more varied randomization would have to be done
	//for more variation in buildings
	int numberOfBaseFloors = rand() % 3;
	int numberOfTopFloors = rand() % 3;

	//A Building is used to construct a structure by stacking other structures (floors) together
	Building newBuilding;

	//Stack bottom floors
	for (int i = 0; i < numberOfTopFloors; i++)
		newBuilding.Stack(bottomFloor);

	//Add an adapter floor
	newBuilding.Stack(transitionFloor);

	//Add the rest
	for (int i = 0; i < numberOfTopFloors; i++)
		newBuilding.Stack(topFloor);

	//At this point some sort of roof should have been added
	//but I didn't make one

	//When you're all done stacking floors
	//call construct once to internally prepare the structure
	//for use
	newBuilding.ConstructStructure();

	//Then call PlaceStructure one or more times to place the structure
	//in whatever 2d positions you want
	//automatically compensates for terrain (no building voxels underneath the ground)
	newBuilding.PlaceStructure(tile,vec2(pos.x,pos.y));

}

void CityGen::construct_city(GameTile * tile, vec3 pos) {
	//First create city points at even intervals
	const static float evenBuildingDistance = 20.0f;
	const static float buildingSize = 15.0f;

	ContiguousList<Rect> buildingPlacements;

	TileCell * cells = tile->Cells;

	vec3 tileOffset = vec3(tile->tile_x,tile->tile_y,0) * vec3(TILE_SIZE,TILE_SIZE,1.0);

	//Warning HACK
	//create savable city data here
	SavableCityData * cityData = new SavableCityData();
	cityData->cityPosition = pos+tileOffset;
	cityData->ownedByPlayer = false;

	float originalCityHeight = cells[int((pos.y)*TILE_SIZE + pos.x)].height;

	//Generate lines
	//set<vec2> usedSpace;
	static const int lineCount = 30;
	static const int turretSkip = 6;
	static const int samples = 200;
	static const float anglePart = M_PI*2.0f/(float)lineCount;

    //flatten terrain
	//generate roads

	for (int y = -citysize / 2; y < citysize / 2; y++) {
		for (int x = -citysize / 2; x < citysize / 2; x++) {
			cells[int((pos.y + y)*TILE_SIZE + pos.x + x)].materialId = 2;
		}
	}

	for (int p = 0; p < lineCount; p++) {
		vec2 lineDirection = glm::normalize(vec2(cos(anglePart*p),sin(anglePart*p)));
		float lineLength = citysize*1.5;
		float lineSection = lineLength/samples;

		if ((p % turretSkip) == 0) {
			//Place turret
			vec2 spos = glm::floor(lineDirection*(-lineLength/2.0f+samples/4*lineSection)) + vec2(pos);

			//raise the height around the turrent
			float newHeight = originalCityHeight +10.0f;
			for (int x = -1; x <= 0; x++) {
				for (int y = -1; y <= 0; y++) {
					vec2 absPos = spos+vec2(x,y);
					TileCell & cell = cells[int((absPos.y)*TILE_SIZE + absPos.x)];
					cell.height = newHeight;
				}
			}

			cityData->gunAlive.push_back(true);
			cityData->gunPositions.push_back(tileOffset+vec3(spos,newHeight));
		}

		//Generate the line by sampling along it

		for (int i = 0; i < samples; i++) {
			//Find the position
			vec2 spos = lineDirection*(-lineLength/2.0f+i*lineSection);
			spos = glm::floor(spos);
			//check that the position is within city limits
			if ((spos.x < -citysize/2.0) || (spos.y < -citysize/2.0))
				continue;
			if ((spos.x > citysize/2.0) || (spos.y > citysize/2.0))
				continue;
			//check that the position isn't too close to the center
			float len = glm::length(spos);
			if (len < 16)
				continue;
			//Place a line here
			float height = (len*len-15*15)*.0008+2;
			vec2 absPos = glm::floor(vec2(pos)+spos);
			TileCell & cell = cells[int((absPos.y)*TILE_SIZE + absPos.x)];
			cell.height += height;
			//City is stronger than surrounding terrain
			cell.cellHealth = 25;
			cell.cellMaxHealth = 25;
		}
	}

	//Different heights in the spire
	int ringHeights[5] = {
		30,
		28,
		24,
		18,
		10
	};

	//Place the spire
	for (float x = -4; x <= 4; x++) {
		for (float y = -4; y <= 4; y++) {
			float ring = max(abs(x),abs(y));
			vec2 spos = vec2(x,y)+vec2(pos);
			TileCell & cell = cells[int((spos.y)*TILE_SIZE + spos.x)];
			cell.height += ringHeights[(int)ring]*3/2;
			//The tower is made of tough stuff
			cell.cellHealth = 50;
			cell.cellMaxHealth = 50;
            cell.materialId = 3;
			//Register the center
			if (ring == 0) {
				cityData->cityCenterVoxel = spos+vec2(tileOffset);
				cityData->originalCityCenterVoxel = cell.height;
			}

		}
	}

	//Super hack, transfer city data to ai
	Game()->Actors.Aids()->RegisterNewCity(cityData);

}

void CityGen::generatecitylocations(GameTile* tile){

	//the amount to blur
	const int blur = 4;

	//analyze the terrain
	//We Differentiate the terrain and then blur it 4x to achieve the effect of inteligent city placement

	//this will store the differential blur of the terrain
	float * analysis = new float[TILE_SIZE*TILE_SIZE];

	//This allows us to access the terrain values
	TileCell * cells = tile->Cells;

	//our operator ignores edges, so set them to be really high
	//This also helps keep cities off the edge of tiles because that breaks things
	for (int y = 0; y < TILE_SIZE; y++) {
		//left
		analysis[y*TILE_SIZE + 0] = 500;
		//right
		analysis[y*TILE_SIZE + TILE_SIZE - 1] = 500;
	}
	//check the x edge and normalize the height so it matches
	for (int x = 0; x < TILE_SIZE; x++) {
		//top
		analysis[0 * TILE_SIZE + x] = 500;
		//bottom
		analysis[(TILE_SIZE - 1)*TILE_SIZE + x] = 500;
	}

	//Get the slope using the Sobel Operator
	for (int y = 1; y < TILE_SIZE - 1; y++) {
		for (int x = 1; x < TILE_SIZE - 1; x++) {
			//directions don't actually matter, we just care about magnitude of change
			float bottomLeftIntensity = cells[TILE_SIZE*(y - 1) + x - 1].height;
			float topRightIntensity = cells[TILE_SIZE*(y + 1) + x + 1].height;
			float topLeftIntensity = cells[TILE_SIZE*(y + 1) + x - 1].height;
			float bottomRightIntensity = cells[TILE_SIZE*(y - 1) + x + 1].height;
			float leftIntensity = cells[TILE_SIZE*(y)+x - 1].height;
			float rightIntensity = cells[TILE_SIZE*(y)+x + 1].height;
			float bottomIntensity = cells[TILE_SIZE*(y - 1) + x].height;
			float topIntensity = cells[TILE_SIZE*(y + 1) + x].height;

			float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;
			float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;

			float mag = glm::length(vec2(h, v));
			analysis[y*TILE_SIZE + x] = mag;
		}
	}

	//Apply Blur 4x
	for (int i = 0; i < blur; i++) {
		for (int y = 1; y < TILE_SIZE - 1; y++) {
			for (int x = 1; x < TILE_SIZE - 1; x++) {
				//directions don't actually matter, we just care about magnitude of change

				float bottomLeftIntensity = analysis[TILE_SIZE*(y - 1) + x - 1];
				float topRightIntensity = analysis[TILE_SIZE*(y + 1) + x + 1];
				float topLeftIntensity = analysis[TILE_SIZE*(y + 1) + x - 1];
				float bottomRightIntensity = analysis[TILE_SIZE*(y - 1) + x + 1];
				float leftIntensity = analysis[TILE_SIZE*(y)+x - 1];
				float rightIntensity = analysis[TILE_SIZE*(y)+x + 1];
				float bottomIntensity = analysis[TILE_SIZE*(y - 1) + x];
				float topIntensity = analysis[TILE_SIZE*(y + 1) + x];

				double top = topIntensity + topLeftIntensity + topRightIntensity;
				double middle = analysis[y*TILE_SIZE + x] + leftIntensity + rightIntensity;
				double bottom = bottomIntensity + bottomLeftIntensity + bottomRightIntensity;

				float average = (top + middle + bottom) / 9;

				analysis[y*TILE_SIZE + x] = average;
			}
		}
	}
	float minheight = 5000;
	vec3 citylocation;

	float noisetolerance = 3;
	float heighttolerance = 5;
	//figure out where to put the city but make sure it doesn't go off the edge
	for (int y = citysize/2+10; y < TILE_SIZE - (citysize/2+10); y++) {
		for (int x = citysize/2+10; x < TILE_SIZE - (citysize/2+10); x++) {
			if (analysis[y*TILE_SIZE + x] < noisetolerance) {

				//check if we're too close to another city
				bool tooclose = false;
				for (int i = 0; i < tile->Cities.size(); i++) {
					if (glm::length(vec2(tile->Cities[i].x - x, tile->Cities[i].y - y)) < cityspacing)
						tooclose = true;
				}

				if (!tooclose) {
					if (abs(cells[(y - citysize / 2)*TILE_SIZE + x - citysize / 2].height - cells[(y + citysize / 2)*TILE_SIZE + x - citysize / 2].height) < heighttolerance &&
						abs(cells[(y - citysize / 2)*TILE_SIZE + x + citysize / 2].height - cells[(y + citysize / 2)*TILE_SIZE + x + citysize / 2].height) < heighttolerance &&
						abs(cells[(y + citysize / 2)*TILE_SIZE + x + citysize / 2].height - cells[(y + citysize / 2)*TILE_SIZE + x - citysize / 2].height) < heighttolerance &&
						abs(cells[(y - citysize / 2)*TILE_SIZE + x + citysize / 2].height - cells[(y - citysize / 2)*TILE_SIZE + x - citysize / 2].height) < heighttolerance
						) {
						//make some cities
						tile->Cities.push_back(vec3(x, y, 0));
						cout << "CITY PLACED AT:" << x << " , " << y << endl;
					}
				}
			}
		}
	}

	//Flatten Terrain
	for (int i = 0; i < tile->Cities.size(); i++) {
		vec3 pos = tile->Cities[i];
		for (int y = -citysize / 2; y < citysize / 2; y++) {
			for (int x = -citysize / 2; x < citysize / 2; x++) {
				cells[int((pos.y + y)*TILE_SIZE + pos.x + x)].height = cells[int((pos.y)*TILE_SIZE + pos.x)].height;
			}
		}
	}

	// TODO : Blur city edges

	/*
	for (int i = 0; i < tile->Cities.size(); i++) {
		vec3 pos = tile->Cities[i];
		//walk along the edge, for each edge walk outward and normalize
		for (int y = pos.y - citysize/2; y < pos.y + citysize/2; y++) {
			//left
			analysis[y*TILE_SIZE + TILE_SIZE - 1] = 500;

			//right
			analysis[y*TILE_SIZE + TILE_SIZE - 1] = 500;
		}
		for (int x = pos.x - citysize / 2; x < pos.x + citysize / 2; x++) {
			//top
			analysis[0 * TILE_SIZE + x] = 500;
			//bottom
			analysis[(TILE_SIZE - 1)*TILE_SIZE + x] = 500;
		}
	}
	*/
	delete [] analysis;
}
void CityGen::GenerateCities(GameTile * tile) {
	generatecitylocations(tile);
	for (int i = 0; i < tile->Cities.size(); i++) {
		construct_city(tile, tile->Cities[i]);
	}
	tile->UpdateTileSection(0, 0, TILE_SIZE, TILE_SIZE);
}
<|endoftext|>


<commit_before>/*
   The MIT License (MIT)

   Copyright (c) 2014

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

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

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

#include "cppparser.h"
#include "cppdom.h"
#include "cppobjfactory.h"
#include "string-utils.h"

#include <algorithm>
#include <fstream>
#include <vector>

std::set<std::string> gMacroNames = {"DECLARE_MESSAGE_MAP",
                                     "DECLARE_DYNAMIC",
                                     "ACPL_DECLARE_MEMBERS",
                                     "DBSYMUTL_MAKE_GETSYMBOLID_FUNCTION",
                                     "DBSYMUTL_MAKE_HASSYMBOLID_FUNCTION",
                                     "DBSYMUTL_MAKE_HASSYMBOLNAME_FUNCTION"};

std::set<std::string> gKnownApiDecorNames = {"ODRX_ABSTRACT", "FIRSTDLL_EXPORT", "GE_DLLEXPIMPORT", "ADESK_NO_VTABLE"};

extern CppCompound* parseStream(char* stm, size_t stmSize);
CppObjFactory*      gObjFactory = nullptr;

CppParser::CppParser(CppObjFactory* objFactory)
  : objFactory_(objFactory)
{
  if (objFactory_ == nullptr)
    objFactory_ = new CppObjFactory;
}

void CppParser::addKnownMacro(std::string knownMacro)
{
  gMacroNames.insert(std::move(knownMacro));
}

void CppParser::addKnownMacros(const std::vector<std::string>& knownMacros)
{
  for (auto& macro : knownMacros)
    gMacroNames.insert(macro);
}

void CppParser::addKnownApiDecor(std::string knownApiDecor)
{
  gKnownApiDecorNames.insert(std::move(knownApiDecor));
}

void CppParser::addKnownApiDecors(const std::vector<std::string>& knownApiDecor)
{
  for (auto& apiDecor : knownApiDecor)
    gKnownApiDecorNames.insert(apiDecor);
}

CppCompound* CppParser::parseFile(const char* filename)
{
  auto         stm         = readFile(filename);
  CppCompound* cppCompound = parseStream(stm.data(), stm.size());
  if (cppCompound == NULL)
    return cppCompound;
  cppCompound->name_ = filename;
  return cppCompound;
}

CppCompound* CppParser::parseStream(char* stm, size_t stmSize)
{
  if (stm == nullptr || stmSize == 0)
    return nullptr;
  gObjFactory = objFactory_;
  return ::parseStream(stm, stmSize);
}

CppProgram* CppParser::loadProgram(const char* szInputPath)
{
  auto program = new CppProgram;
  loadProgram(szInputPath, *program);
  return program;
}

static void collectFiles(const bfs::path& path, std::vector<std::string>& files)
{
  if (bfs::is_regular_file(path))
  {
    files.push_back(path.string());
  }
  else if (bfs::is_directory(path))
  {
    for (bfs::directory_iterator dirItr(path); dirItr != bfs::directory_iterator(); ++dirItr)
    {
      collectFiles(*dirItr, files);
    }
  }
}

static std::vector<std::string> collectFiles(const bfs::path& path)
{
  std::vector<std::string> files;
  collectFiles(path, files);
  if (!files.empty())
    std::sort(files.begin(), files.end());

  return files;
}

void CppParser::loadProgram(const bfs::path& path, CppProgram& program)
{
  auto files = collectFiles(path);
  for (const auto& f : files)
  {
    auto cppDom = parseFile(f.c_str());
    if (cppDom)
      program.addCppDom(cppDom);
  }
}

CppParser::ByteArray CppParser::readFile(const char* filename)
{
  ByteArray     contents;
  std::ifstream in(filename, std::ios::in | std::ios::binary);
  if (in)
  {
    in.seekg(0, std::ios::end);
    size_t size = in.tellg();
    contents.resize(size + 3); // For adding last 2 nulls and a new line.
    in.seekg(0, std::ios::beg);
    in.read(&contents[0], size);
    in.close();
    auto len = stripChar(contents.data(), size, '\r');
    assert(len <= size);
    contents.resize(len+3);
    contents[len] = '\n';
    contents[len+1] = '\0';
    contents[len+2] = '\0';
  }
  return (contents);
}
<commit_msg>Adding a known arx macro.<commit_after>/*
   The MIT License (MIT)

   Copyright (c) 2014

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

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

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

#include "cppparser.h"
#include "cppdom.h"
#include "cppobjfactory.h"
#include "string-utils.h"

#include <algorithm>
#include <fstream>
#include <vector>

std::set<std::string> gMacroNames = {"DECLARE_MESSAGE_MAP",
                                     "DECLARE_DYNAMIC",
                                     "ACPL_DECLARE_MEMBERS",
                                     "DBSYMUTL_MAKE_GETSYMBOLID_FUNCTION",
                                     "DBSYMUTL_MAKE_HASSYMBOLID_FUNCTION",
                                     "DBSYMUTL_MAKE_HASSYMBOLNAME_FUNCTION"};

std::set<std::string> gKnownApiDecorNames = {"ODRX_ABSTRACT",
                                             "FIRSTDLL_EXPORT",
                                             "GE_DLLEXPIMPORT",
                                             "ADESK_NO_VTABLE",
                                             "ACDBCORE2D_PORT",
                                             "ACBASE_PORT"};

extern CppCompound* parseStream(char* stm, size_t stmSize);
CppObjFactory*      gObjFactory = nullptr;

CppParser::CppParser(CppObjFactory* objFactory)
  : objFactory_(objFactory)
{
  if (objFactory_ == nullptr)
    objFactory_ = new CppObjFactory;
}

void CppParser::addKnownMacro(std::string knownMacro)
{
  gMacroNames.insert(std::move(knownMacro));
}

void CppParser::addKnownMacros(const std::vector<std::string>& knownMacros)
{
  for (auto& macro : knownMacros)
    gMacroNames.insert(macro);
}

void CppParser::addKnownApiDecor(std::string knownApiDecor)
{
  gKnownApiDecorNames.insert(std::move(knownApiDecor));
}

void CppParser::addKnownApiDecors(const std::vector<std::string>& knownApiDecor)
{
  for (auto& apiDecor : knownApiDecor)
    gKnownApiDecorNames.insert(apiDecor);
}

CppCompound* CppParser::parseFile(const char* filename)
{
  auto         stm         = readFile(filename);
  CppCompound* cppCompound = parseStream(stm.data(), stm.size());
  if (cppCompound == NULL)
    return cppCompound;
  cppCompound->name_ = filename;
  return cppCompound;
}

CppCompound* CppParser::parseStream(char* stm, size_t stmSize)
{
  if (stm == nullptr || stmSize == 0)
    return nullptr;
  gObjFactory = objFactory_;
  return ::parseStream(stm, stmSize);
}

CppProgram* CppParser::loadProgram(const char* szInputPath)
{
  auto program = new CppProgram;
  loadProgram(szInputPath, *program);
  return program;
}

static void collectFiles(const bfs::path& path, std::vector<std::string>& files)
{
  if (bfs::is_regular_file(path))
  {
    files.push_back(path.string());
  }
  else if (bfs::is_directory(path))
  {
    for (bfs::directory_iterator dirItr(path); dirItr != bfs::directory_iterator(); ++dirItr)
    {
      collectFiles(*dirItr, files);
    }
  }
}

static std::vector<std::string> collectFiles(const bfs::path& path)
{
  std::vector<std::string> files;
  collectFiles(path, files);
  if (!files.empty())
    std::sort(files.begin(), files.end());

  return files;
}

void CppParser::loadProgram(const bfs::path& path, CppProgram& program)
{
  auto files = collectFiles(path);
  for (const auto& f : files)
  {
    auto cppDom = parseFile(f.c_str());
    if (cppDom)
      program.addCppDom(cppDom);
  }
}

CppParser::ByteArray CppParser::readFile(const char* filename)
{
  ByteArray     contents;
  std::ifstream in(filename, std::ios::in | std::ios::binary);
  if (in)
  {
    in.seekg(0, std::ios::end);
    size_t size = in.tellg();
    contents.resize(size + 3); // For adding last 2 nulls and a new line.
    in.seekg(0, std::ios::beg);
    in.read(&contents[0], size);
    in.close();
    auto len = stripChar(contents.data(), size, '\r');
    assert(len <= size);
    contents.resize(len + 3);
    contents[len]     = '\n';
    contents[len + 1] = '\0';
    contents[len + 2] = '\0';
  }
  return (contents);
}
<|endoftext|>


<commit_before>/*
    В языке С++ базовая работа с символами и строками аналогична C.

    Символы заключаются в одинарные кавычки
        'a', '8', '&', ' '

    Фактически, каждый символ представляет из себя некоторый знак: буквы, цифра, плюс, минус и прочие.
    Однако, в C/C++ некоторые символы состоят из нескольких знаков. Как пример, набор слеш-последовательностей:
        '\n' - символ новой строки. Сам символ - один, но представлен двумя знаками
        '\t' - символ табуляции. Аналогичный случай.

    Для работы с символами в C используется тип char
        char symb1 = '4', symb2 = 'a';

    Для вывода символа на консоль осуществляется так:
        cout << symb1; // вывести переменную типа char на экран
    или так:
        cout.put(symb1);

    Получить символ с стандартного потока ввода можно так:
        cin >> symb2; // считать первый введённый символ в переменную symb2
    или так:
        cin.get(symb2);
    и даже так:
        symb2 = cin.get(); // правда тут cin.get() возращает целое число типа int

    Каждому символу сопостовляется внутренний код - целое число. Поэтому с переменными
    типа char можно обращаться как с целочисленными величинами. Более того, порядок кодов символов
    неизменен, для примера - смотрите таблицу ASCII кодов в пособии. Из-за этого, символы могут
    принимать участие в арифметических операциях и операциях сравнения:
        char sym = '1';

        sym += 1; // увеличит код символа на 1. В соответствии с таблицей ASCII
                  // в переменной sym будет находится символ двойки: '2';

        if ( sym > '5' ) { // сравниваем символы
            // не выполнится, потому что '2' раньше '5'
        } else {
            cout << "Else branch";
        }

        int code = int( sym ); // получение целочисленного кода определённого символа с помощью приведения типов

        if ( sym >= '0' && sym <= '9' ) { // проверяем, что в переменной sym находится символ цифры
            ...
        }

    ************************************************************************************
    Под строкой понимается набор символов, заключённых в двойные кавычки:
        "A simple string"
        "89983 - something important"
        "abcdefg"

    Для строк не введён специальный тип. Для их хранения используется массив типа char:
        char str[] = "Str1"; // В C++ такие строки называют "строками в стиле C".
    Выше определяется массив str типа char. Ему присваивается строка "Str1".
    Из-за особенностей массивов в C было принято, что последним символом должен обязательно идти
    символ конца строки - '\0'. Таким образом, str представляется в виде массива из 5 символов:
        ['S', 't', 'r', '1', '\0']
    При том, что в исходной строке - всего 4 символа. Для C наличие символа конца строки очень важно,
    все функции обработки строк предполагают, что переданные им массивы будут содержать в себе
    этот символ последним элементом.

    Определение str может быть сделано в явном виде как обычный массив:
        char str[] = {'S', 't', 'r', '1', '\0'};

    При этом, нельзя присваивать строку в двойных кавычках уже объявленным массивам:
        char word[10];
        word = "true"; //Ошибка!

    Вывести строку на экран можно так:
        char word[] = "word";
        cout << word;

    Ввод строки:
        char str[30];
        cout << "Enter string:" << endl;
        cin.getline(str, 30); // 30 - размер массива. Максимально будет считано 29 символов и последним добавлен символ конца строки - '\0'
                              // Если было введено менее 30 символов, то все они помещаются в sentence
                              // и после последнего символа помещается символ конца строки. Но
                              // в этом случае в строку попадает и символ переноса строки - '\n'

    Выше указанные функции ввода-вывода опеределены в <iostream>

    Также имеется набор функций из стандартной библиотеки C для работы со строками, определённых в <cstring>.
    Например:
        // Определяем строку, содержащую 32 символа.
        char str[] = "a_long_long_long_word_as_example";
        // Размер массива str в данном случае - 33 символа

        // Функция strlen возращает количество символов в строке
        // без учёта символа конца строки ('\0')
        cout << "The size of str is " << strlen(str) << endl; // будет напечатано: "The size of str is 32"
    Другие примеры - непосредственно в программе.
*/

#include <iostream>
#include <cstring> // strlen и другие функции работы со строками

using namespace std;

void print_eng_letters()
{
    char sym = 'a'; // объявляем переменную типа char и присваиваем ей значение

    cout << "English lowercase letters:" << endl;
    // печатаем все цифры
    while ( sym <= 'z' ) {
        cout.put(sym);
        ++sym; // используем операцию инкремента для увеличения кода символа на единицу
               // тоже самое, что и sym += 1
    }
    cout << endl;
}

int main()
{
    print_eng_letters();

    char letter = 'W';
    // Печатаем букву 'W' и её целочисленный код
    cout << "The symbol and the code: " << letter << " : " << int( letter ) << endl;

    // Объявляем и инициализируем строку
    char first_str[] = "A very very important sentence";

    // вычисляем количество элементов в массиве first_str
    unsigned int char_array_size = sizeof(first_str) / sizeof(first_str[0]);
    // Печатаем строку, её длину с помощью функции strlen, и длину массива first_arr
    // Последние два значения будут различаться на единицу.
    cout << "The string: " << first_str << endl;
    cout << "String size: " << strlen(first_str) << endl;
    cout << "Array size: " << char_array_size << endl << endl;

    /*
        Демонстрация функции strcmp из <string.h>
        Данная функция принимает два аргумента - две строки - и сравнивает из посимвольно.
        Возращает         0    : если все символы совпадают
          значение меньше 0    : если код первого несовпадающего символа в первой строке меньше кода символа во второй строке
          значение больше 0    : если код первого несовпадающего символа в первой строке больше кода символа во второй строке
    */
    char secret_str[] = "just cat"; // задаём строку, при вводе которой будет прерван бесконечный цикл
    char buffer[80];                // массив для хранения введённой пользователем строки

    do {
        cout << "Guess secret string? "; // просим угадать выше определённую строку
        cin.getline(buffer, 80);        // считываем введённую строку
    } while ( strcmp(secret_str, buffer) != 0 ); // проверяем результат функции сравнения строк
    cout << "Correct answer!" << endl;

    /*
        Пример функция strcpy и strncat из string.h
    */
    char str1[20], str2[20], str3[] = "or not to be";
    strcpy(str1, "To be ");         // копируем вторую строку в первую. Даже если в str1 были какие-то символы, они замещаются
                                    // символами из второй строки
    strcpy(str2, str3);             // копируем str3 в str2
    strncat(str1, str2, 6);         // добавляем первые 6 символов из str2 в str1
    cout << str1;                   // печатаем ""To be or not"

    return 0;
}
<commit_msg>fix header name in base_strings_characters.cpp<commit_after>/*
    В языке С++ базовая работа с символами и строками аналогична C.

    Символы заключаются в одинарные кавычки
        'a', '8', '&', ' '

    Фактически, каждый символ представляет из себя некоторый знак: буквы, цифра, плюс, минус и прочие.
    Однако, в C/C++ некоторые символы состоят из нескольких знаков. Как пример, набор слеш-последовательностей:
        '\n' - символ новой строки. Сам символ - один, но представлен двумя знаками
        '\t' - символ табуляции. Аналогичный случай.

    Для работы с символами в C используется тип char
        char symb1 = '4', symb2 = 'a';

    Для вывода символа на консоль осуществляется так:
        cout << symb1; // вывести переменную типа char на экран
    или так:
        cout.put(symb1);

    Получить символ с стандартного потока ввода можно так:
        cin >> symb2; // считать первый введённый символ в переменную symb2
    или так:
        cin.get(symb2);
    и даже так:
        symb2 = cin.get(); // правда тут cin.get() возращает целое число типа int

    Каждому символу сопостовляется внутренний код - целое число. Поэтому с переменными
    типа char можно обращаться как с целочисленными величинами. Более того, порядок кодов символов
    неизменен, для примера - смотрите таблицу ASCII кодов в пособии. Из-за этого, символы могут
    принимать участие в арифметических операциях и операциях сравнения:
        char sym = '1';

        sym += 1; // увеличит код символа на 1. В соответствии с таблицей ASCII
                  // в переменной sym будет находится символ двойки: '2';

        if ( sym > '5' ) { // сравниваем символы
            // не выполнится, потому что '2' раньше '5'
        } else {
            cout << "Else branch";
        }

        int code = int( sym ); // получение целочисленного кода определённого символа с помощью приведения типов

        if ( sym >= '0' && sym <= '9' ) { // проверяем, что в переменной sym находится символ цифры
            ...
        }

    ************************************************************************************
    Под строкой понимается набор символов, заключённых в двойные кавычки:
        "A simple string"
        "89983 - something important"
        "abcdefg"

    Для строк не введён специальный тип. Для их хранения используется массив типа char:
        char str[] = "Str1"; // В C++ такие строки называют "строками в стиле C".
    Выше определяется массив str типа char. Ему присваивается строка "Str1".
    Из-за особенностей массивов в C было принято, что последним символом должен обязательно идти
    символ конца строки - '\0'. Таким образом, str представляется в виде массива из 5 символов:
        ['S', 't', 'r', '1', '\0']
    При том, что в исходной строке - всего 4 символа. Для C наличие символа конца строки очень важно,
    все функции обработки строк предполагают, что переданные им массивы будут содержать в себе
    этот символ последним элементом.

    Определение str может быть сделано в явном виде как обычный массив:
        char str[] = {'S', 't', 'r', '1', '\0'};

    При этом, нельзя присваивать строку в двойных кавычках уже объявленным массивам:
        char word[10];
        word = "true"; //Ошибка!

    Вывести строку на экран можно так:
        char word[] = "word";
        cout << word;

    Ввод строки:
        char str[30];
        cout << "Enter string:" << endl;
        cin.getline(str, 30); // 30 - размер массива. Максимально будет считано 29 символов и последним добавлен символ конца строки - '\0'
                              // Если было введено менее 30 символов, то все они помещаются в sentence
                              // и после последнего символа помещается символ конца строки. Но
                              // в этом случае в строку попадает и символ переноса строки - '\n'

    Выше указанные функции ввода-вывода опеределены в <iostream>

    Также имеется набор функций из стандартной библиотеки C для работы со строками, определённых в <cstring>.
    Например:
        // Определяем строку, содержащую 32 символа.
        char str[] = "a_long_long_long_word_as_example";
        // Размер массива str в данном случае - 33 символа

        // Функция strlen возращает количество символов в строке
        // без учёта символа конца строки ('\0')
        cout << "The size of str is " << strlen(str) << endl; // будет напечатано: "The size of str is 32"
    Другие примеры - непосредственно в программе.
*/

#include <iostream>
#include <cstring> // strlen и другие функции работы со строками

using namespace std;

void print_eng_letters()
{
    char sym = 'a'; // объявляем переменную типа char и присваиваем ей значение

    cout << "English lowercase letters:" << endl;
    // печатаем все цифры
    while ( sym <= 'z' ) {
        cout.put(sym);
        ++sym; // используем операцию инкремента для увеличения кода символа на единицу
               // тоже самое, что и sym += 1
    }
    cout << endl;
}

int main()
{
    print_eng_letters();

    char letter = 'W';
    // Печатаем букву 'W' и её целочисленный код
    cout << "The symbol and the code: " << letter << " : " << int( letter ) << endl;

    // Объявляем и инициализируем строку
    char first_str[] = "A very very important sentence";

    // вычисляем количество элементов в массиве first_str
    unsigned int char_array_size = sizeof(first_str) / sizeof(first_str[0]);
    // Печатаем строку, её длину с помощью функции strlen, и длину массива first_arr
    // Последние два значения будут различаться на единицу.
    cout << "The string: " << first_str << endl;
    cout << "String size: " << strlen(first_str) << endl;
    cout << "Array size: " << char_array_size << endl << endl;

    /*
        Демонстрация функции strcmp из <cstring>
        Данная функция принимает два аргумента - две строки - и сравнивает из посимвольно.
        Возращает         0    : если все символы совпадают
          значение меньше 0    : если код первого несовпадающего символа в первой строке меньше кода символа во второй строке
          значение больше 0    : если код первого несовпадающего символа в первой строке больше кода символа во второй строке
    */
    char secret_str[] = "just cat"; // задаём строку, при вводе которой будет прерван бесконечный цикл
    char buffer[80];                // массив для хранения введённой пользователем строки

    do {
        cout << "Guess secret string? "; // просим угадать выше определённую строку
        cin.getline(buffer, 80);        // считываем введённую строку
    } while ( strcmp(secret_str, buffer) != 0 ); // проверяем результат функции сравнения строк
    cout << "Correct answer!" << endl;

    /*
        Пример функция strcpy и strncat из <cstring>
    */
    char str1[20], str2[20], str3[] = "or not to be";
    strcpy(str1, "To be ");         // копируем вторую строку в первую. Даже если в str1 были какие-то символы, они замещаются
                                    // символами из второй строки
    strcpy(str2, str3);             // копируем str3 в str2
    strncat(str1, str2, 6);         // добавляем первые 6 символов из str2 в str1
    cout << str1;                   // печатаем ""To be or not"

    return 0;
}
<|endoftext|>


<commit_before>#ifndef __KD_TREE_HPP_
#define __KD_TREE_HPP_

#include <string>
#include <iostream>
#include <vector>

//______________________________________________________________________________
class Point {
   public :

      // constructors
      Point();
      Point(double x, double y, double z);
      Point(const Point& other);
      bool operator==(const Point& other) const;

      virtual ~Point();

      // getters
      double X() const {return fX;}
      double Y() const {return fY;}
      double Z() const {return fZ;}

      // setters
      void SetX(double x){fX=x;}
      void SetY(double y){fY=y;}
      void SetZ(double z){fZ=z;}

      std::string ToString() const;
      double DistanceTo(const Point& point) const;
      double SquaredDistanceTo(const Point& point) const;

   private:
      double fX,fY,fZ;
};

class sortX {
	public:
	bool operator() (Point *a, Point *b) { return ((*a).X() < (*b).X());}
};

class sortY {
	public:
	bool operator() (Point *a, Point *b) { return ((*a).Y() < (*b).Y());}
};

class sortZ {
	public:
	bool operator() (Point *a, Point *b) { return ((*a).Z() < (*b).Z());}
};

//______________________________________________________________________________
class KDTreeNode {
public:
   KDTreeNode();
   KDTreeNode(const KDTreeNode& other);
   virtual ~KDTreeNode();

   void SetDepth(int depth) {fDepth = depth;}
   void SetPoint(Point* otherPoint) {fPoint = otherPoint;}
   void SetParent(KDTreeNode* other) {fParent = other;}
   void SetLeftChild(KDTreeNode* otherLeft) {fLeft = otherLeft;}
   void SetRightChild(KDTreeNode* otherRight) {fRight = otherRight;}

   int GetDepth() const {return fDepth;}
   const Point& GetPoint() const {return *fPoint;}
   const KDTreeNode* GetParent() const {return fParent;}
   const KDTreeNode* GetLeftChild() const {return fLeft;}
   const KDTreeNode* GetRightChild() const {return fRight;}

   const KDTreeNode& FindNodeContaining(const Point& point) const;
   const KDTreeNode& CheckParentForCloserNodes(const Point& point, const KDTreeNode& best) const;

   void OutputGraphViz(std::ostream& out) const;

private:
   int fDepth;
   Point* fPoint;
   KDTreeNode *fParent;
   KDTreeNode *fLeft;
   KDTreeNode *fRight;

   bool CheckOtherSideofSplittingPlane(const Point& point, const double radius) const;
   const KDTreeNode& SearchChildren(const Point& point, const KDTreeNode& currentBest) const;
   bool IsCloserToPoint(const Point& point, const KDTreeNode& currentBest) const;
};

//______________________________________________________________________________
class KDTree {
   public:
      KDTree(std::vector<Point*>& pointList);
      KDTree(const KDTree& other);
      virtual ~KDTree();

      const Point& NearestNeighbour(const Point& point) const;
      void OutputGraphViz(std::ostream& out) const;

   private:
      KDTreeNode *fRoot;

      KDTreeNode* BuildNode(std::vector<Point*>& pointList, KDTreeNode* parent, int depth=0);

};

#endif
<commit_msg>Levelled up an int to unsigned int<commit_after>#ifndef __KD_TREE_HPP_
#define __KD_TREE_HPP_

#include <string>
#include <iostream>
#include <vector>

//______________________________________________________________________________
class Point {
   public :

      // constructors
      Point();
      Point(double x, double y, double z);
      Point(const Point& other);
      bool operator==(const Point& other) const;

      virtual ~Point();

      // getters
      double X() const {return fX;}
      double Y() const {return fY;}
      double Z() const {return fZ;}

      // setters
      void SetX(double x){fX=x;}
      void SetY(double y){fY=y;}
      void SetZ(double z){fZ=z;}

      std::string ToString() const;
      double DistanceTo(const Point& point) const;
      double SquaredDistanceTo(const Point& point) const;

   private:
      double fX,fY,fZ;
};

class sortX {
	public:
	bool operator() (Point *a, Point *b) { return ((*a).X() < (*b).X());}
};

class sortY {
	public:
	bool operator() (Point *a, Point *b) { return ((*a).Y() < (*b).Y());}
};

class sortZ {
	public:
	bool operator() (Point *a, Point *b) { return ((*a).Z() < (*b).Z());}
};

//______________________________________________________________________________
class KDTreeNode {
public:
   KDTreeNode();
   KDTreeNode(const KDTreeNode& other);
   virtual ~KDTreeNode();

   void SetDepth(int depth) {fDepth = depth;}
   void SetPoint(Point* otherPoint) {fPoint = otherPoint;}
   void SetParent(KDTreeNode* other) {fParent = other;}
   void SetLeftChild(KDTreeNode* otherLeft) {fLeft = otherLeft;}
   void SetRightChild(KDTreeNode* otherRight) {fRight = otherRight;}

   int GetDepth() const {return fDepth;}
   const Point& GetPoint() const {return *fPoint;}
   const KDTreeNode* GetParent() const {return fParent;}
   const KDTreeNode* GetLeftChild() const {return fLeft;}
   const KDTreeNode* GetRightChild() const {return fRight;}

   const KDTreeNode& FindNodeContaining(const Point& point) const;
   const KDTreeNode& CheckParentForCloserNodes(const Point& point, const KDTreeNode& best) const;

   void OutputGraphViz(std::ostream& out) const;

private:
   unsigned int fDepth;
   Point* fPoint;
   KDTreeNode *fParent;
   KDTreeNode *fLeft;
   KDTreeNode *fRight;

   bool CheckOtherSideofSplittingPlane(const Point& point, const double radius) const;
   const KDTreeNode& SearchChildren(const Point& point, const KDTreeNode& currentBest) const;
   bool IsCloserToPoint(const Point& point, const KDTreeNode& currentBest) const;
};

//______________________________________________________________________________
class KDTree {
   public:
      KDTree(std::vector<Point*>& pointList);
      KDTree(const KDTree& other);
      virtual ~KDTree();

      const Point& NearestNeighbour(const Point& point) const;
      void OutputGraphViz(std::ostream& out) const;

   private:
      KDTreeNode *fRoot;

      KDTreeNode* BuildNode(std::vector<Point*>& pointList, KDTreeNode* parent, int depth=0);

};

#endif
<|endoftext|>


<commit_before>#include <seqan/basic.h>
#include <seqan/seq_io.h>
#include <seqan/sequence.h>

using namespace seqan;

int main(int argc, char ** argv)
{
    CharString path = SEQAN_TEMP_FILENAME();
    append(path, ".fa");

    // Open file and check for errors.
    SequenceStream seqStream(toCString(path), SequenceStream::WRITE);
    if (!isGood(seqStream))
    {
        std::cerr << "ERROR: Could not open " << path << " for writing.\n";
        return 1;
    }

    // Write two sequences to the file.
    if (writeRecord(seqStream, "one", "CGAT") != 0 ||
        writeRecord(seqStream, "two", "ASDF") != 0)
    {
        std::cerr << "ERROR: Problem writing to " << path << "\n";
        return 1;
    }

    return 0;
}
<commit_msg>[INTERNAL] SequenceFile: updated writing demo<commit_after>#include <seqan/basic.h>
#include <seqan/sequence.h>
#include <seqan/seq_io.h>

using namespace seqan;

int main(int argc, char ** argv)
{
    CharString path = SEQAN_TEMP_FILENAME();
    append(path, ".fa");

    SequenceFile<Output> file(toCString(path));

    CharString meta = "chr1";
    CharString seq = "ACGT";

    write(file, meta, seq);

    close(file);

    return 0;
}
<|endoftext|>


<commit_before>#ifndef SELECTION_BOILERPLATE_HPP
#define SELECTION_BOILERPLATE_HPP

#include <atomic>
#include <libnest2d/libnest2d.hpp>

namespace libnest2d { namespace selections {

template<class RawShape>
class SelectionBoilerplate {
public:
    using ShapeType = RawShape;
    using Item = _Item<RawShape>;
    using ItemGroup = _ItemGroup<RawShape>;
    using PackGroup = _PackGroup<RawShape>;

    inline const PackGroup& getResult() const {
        return packed_bins_;
    }

    inline void progressIndicator(ProgressFunction fn) { progress_ = fn; }

    inline void stopCondition(StopCondition cond) { stopcond_ = cond; }

    inline void clear() { packed_bins_.clear(); }

protected:

    template<class Placer, class Container, class Bin, class PCfg>
    void remove_unpackable_items(Container &c, const Bin &bin, const PCfg& pcfg)
    {
        // Safety test: try to pack each item into an empty bin. If it fails
        // then it should be removed from the list
        auto it = c.begin();
        while (it != c.end() && !stopcond_()) {
            Placer p{bin};
            p.configure(pcfg);
            const Item& itm = *it;
            Item cpy{itm};
            if (!p.pack(cpy)) it = c.erase(it);
            else it++;
        }
    }

    PackGroup packed_bins_;
    ProgressFunction progress_ = [](unsigned){};
    StopCondition stopcond_ = [](){ return false; };
};

}
}

#endif // SELECTION_BOILERPLATE_HPP
<commit_msg>Fix arrange crash with ASAN<commit_after>#ifndef SELECTION_BOILERPLATE_HPP
#define SELECTION_BOILERPLATE_HPP

#include <atomic>
#include <libnest2d/libnest2d.hpp>

namespace libnest2d { namespace selections {

template<class RawShape>
class SelectionBoilerplate {
public:
    using ShapeType = RawShape;
    using Item = _Item<RawShape>;
    using ItemGroup = _ItemGroup<RawShape>;
    using PackGroup = _PackGroup<RawShape>;

    inline const PackGroup& getResult() const {
        return packed_bins_;
    }

    inline void progressIndicator(ProgressFunction fn) { progress_ = fn; }

    inline void stopCondition(StopCondition cond) { stopcond_ = cond; }

    inline void clear() { packed_bins_.clear(); }

protected:

    template<class Placer, class Container, class Bin, class PCfg>
    void remove_unpackable_items(Container &c, const Bin &bin, const PCfg& pcfg)
    {
        // Safety test: try to pack each item into an empty bin. If it fails
        // then it should be removed from the list
        auto it = c.begin();
        while (it != c.end() && !stopcond_()) {

            // WARNING: The copy of itm needs to be created before Placer.
            // Placer is working with references and its destructor still
            // manipulates the item this is why the order of stack creation
            // matters here.
            const Item& itm = *it;
            Item cpy{itm};

            Placer p{bin};
            p.configure(pcfg);
            if (!p.pack(cpy)) it = c.erase(it);
            else it++;
        }
    }

    PackGroup packed_bins_;
    ProgressFunction progress_ = [](unsigned){};
    StopCondition stopcond_ = [](){ return false; };
};

}
}

#endif // SELECTION_BOILERPLATE_HPP
<|endoftext|>