<commit_before>/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"

#include "core/svg/SVGPatternElement.h"

#include "XLinkNames.h"
#include "core/rendering/svg/RenderSVGResourcePattern.h"
#include "core/svg/PatternAttributes.h"
#include "core/svg/SVGElementInstance.h"
#include "platform/transforms/AffineTransform.h"

namespace WebCore {

// Animated property definitions
DEFINE_ANIMATED_ENUMERATION(SVGPatternElement, SVGNames::patternUnitsAttr, PatternUnits, patternUnits, SVGUnitTypes::SVGUnitType)
DEFINE_ANIMATED_ENUMERATION(SVGPatternElement, SVGNames::patternContentUnitsAttr, PatternContentUnits, patternContentUnits, SVGUnitTypes::SVGUnitType)
DEFINE_ANIMATED_TRANSFORM_LIST(SVGPatternElement, SVGNames::patternTransformAttr, PatternTransform, patternTransform)
DEFINE_ANIMATED_STRING(SVGPatternElement, XLinkNames::hrefAttr, Href, href)
DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGPatternElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio)

BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGPatternElement)
    REGISTER_LOCAL_ANIMATED_PROPERTY(patternUnits)
    REGISTER_LOCAL_ANIMATED_PROPERTY(patternContentUnits)
    REGISTER_LOCAL_ANIMATED_PROPERTY(patternTransform)
    REGISTER_LOCAL_ANIMATED_PROPERTY(href)
    REGISTER_LOCAL_ANIMATED_PROPERTY(preserveAspectRatio)
    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGElement)
    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests)
END_REGISTER_ANIMATED_PROPERTIES

inline SVGPatternElement::SVGPatternElement(Document& document)
    : SVGElement(SVGNames::patternTag, document)
    , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth)))
    , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight)))
    , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth)))
    , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight)))
    , m_viewBox(SVGAnimatedRect::create(this, SVGNames::viewBoxAttr))
    , m_patternUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
    , m_patternContentUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
{
    ScriptWrappable::init(this);

    addToPropertyMap(m_x);
    addToPropertyMap(m_y);
    addToPropertyMap(m_width);
    addToPropertyMap(m_height);
    addToPropertyMap(m_viewBox);
    registerAnimatedPropertiesForSVGPatternElement();
}

PassRefPtr<SVGPatternElement> SVGPatternElement::create(Document& document)
{
    return adoptRef(new SVGPatternElement(document));
}

bool SVGPatternElement::isSupportedAttribute(const QualifiedName& attrName)
{
    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
    if (supportedAttributes.isEmpty()) {
        SVGURIReference::addSupportedAttributes(supportedAttributes);
        SVGTests::addSupportedAttributes(supportedAttributes);
        SVGFitToViewBox::addSupportedAttributes(supportedAttributes);
        supportedAttributes.add(SVGNames::patternUnitsAttr);
        supportedAttributes.add(SVGNames::patternContentUnitsAttr);
        supportedAttributes.add(SVGNames::patternTransformAttr);
        supportedAttributes.add(SVGNames::xAttr);
        supportedAttributes.add(SVGNames::yAttr);
        supportedAttributes.add(SVGNames::widthAttr);
        supportedAttributes.add(SVGNames::heightAttr);
    }
    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
}

void SVGPatternElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    SVGParsingError parseError = NoError;

    if (!isSupportedAttribute(name))
        SVGElement::parseAttribute(name, value);
    else if (name == SVGNames::patternUnitsAttr) {
        SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
        if (propertyValue > 0)
            setPatternUnitsBaseValue(propertyValue);
        return;
    } else if (name == SVGNames::patternContentUnitsAttr) {
        SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
        if (propertyValue > 0)
            setPatternContentUnitsBaseValue(propertyValue);
        return;
    } else if (name == SVGNames::patternTransformAttr) {
        SVGTransformList newList;
        newList.parse(value);
        detachAnimatedPatternTransformListWrappers(newList.size());
        setPatternTransformBaseValue(newList);
        return;
    } else if (name == SVGNames::xAttr)
        m_x->setBaseValueAsString(value, AllowNegativeLengths, parseError);
    else if (name == SVGNames::yAttr)
        m_y->setBaseValueAsString(value, AllowNegativeLengths, parseError);
    else if (name == SVGNames::widthAttr)
        m_width->setBaseValueAsString(value, ForbidNegativeLengths, parseError);
    else if (name == SVGNames::heightAttr)
        m_height->setBaseValueAsString(value, ForbidNegativeLengths, parseError);
    else if (SVGURIReference::parseAttribute(name, value)
             || SVGTests::parseAttribute(name, value)
             || SVGFitToViewBox::parseAttribute(this, name, value)) {
    } else
        ASSERT_NOT_REACHED();

    reportAttributeParsingError(parseError, name, value);
}

void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName)
{
    if (!isSupportedAttribute(attrName)) {
        SVGElement::svgAttributeChanged(attrName);
        return;
    }

    SVGElementInstance::InvalidationGuard invalidationGuard(this);

    if (attrName == SVGNames::xAttr
        || attrName == SVGNames::yAttr
        || attrName == SVGNames::widthAttr
        || attrName == SVGNames::heightAttr)
        updateRelativeLengthsInformation();

    RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
    if (renderer)
        renderer->invalidateCacheAndMarkForLayout();
}

void SVGPatternElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
    SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);

    if (changedByParser)
        return;

    if (RenderObject* object = renderer())
        object->setNeedsLayout();
}

RenderObject* SVGPatternElement::createRenderer(RenderStyle*)
{
    return new RenderSVGResourcePattern(this);
}

void SVGPatternElement::collectPatternAttributes(PatternAttributes& attributes) const
{
    HashSet<const SVGPatternElement*> processedPatterns;

    const SVGPatternElement* current = this;
    while (current) {
        if (!attributes.hasX() && current->hasAttribute(SVGNames::xAttr))
            attributes.setX(current->x()->currentValue());

        if (!attributes.hasY() && current->hasAttribute(SVGNames::yAttr))
            attributes.setY(current->y()->currentValue());

        if (!attributes.hasWidth() && current->hasAttribute(SVGNames::widthAttr))
            attributes.setWidth(current->width()->currentValue());

        if (!attributes.hasHeight() && current->hasAttribute(SVGNames::heightAttr))
            attributes.setHeight(current->height()->currentValue());

        if (!attributes.hasViewBox() && current->hasAttribute(SVGNames::viewBoxAttr) && current->viewBox()->currentValue()->isValid())
            attributes.setViewBox(current->viewBox()->currentValue()->value());

        if (!attributes.hasPreserveAspectRatio() && current->hasAttribute(SVGNames::preserveAspectRatioAttr))
            attributes.setPreserveAspectRatio(current->preserveAspectRatioCurrentValue());

        if (!attributes.hasPatternUnits() && current->hasAttribute(SVGNames::patternUnitsAttr))
            attributes.setPatternUnits(current->patternUnitsCurrentValue());

        if (!attributes.hasPatternContentUnits() && current->hasAttribute(SVGNames::patternContentUnitsAttr))
            attributes.setPatternContentUnits(current->patternContentUnitsCurrentValue());

        if (!attributes.hasPatternTransform() && current->hasAttribute(SVGNames::patternTransformAttr)) {
            AffineTransform transform;
            current->patternTransformCurrentValue().concatenate(transform);
            attributes.setPatternTransform(transform);
        }

        if (!attributes.hasPatternContentElement() && current->childElementCount())
            attributes.setPatternContentElement(current);

        processedPatterns.add(current);

        // Respect xlink:href, take attributes from referenced element
        Node* refNode = SVGURIReference::targetElementFromIRIString(current->hrefCurrentValue(), document());
        if (refNode && refNode->hasTagName(SVGNames::patternTag)) {
            current = toSVGPatternElement(const_cast<const Node*>(refNode));

            // Cycle detection
            if (processedPatterns.contains(current)) {
                current = 0;
                break;
            }
        } else
            current = 0;
    }
}

AffineTransform SVGPatternElement::localCoordinateSpaceTransform(SVGElement::CTMScope) const
{
    AffineTransform matrix;
    patternTransformCurrentValue().concatenate(matrix);
    return matrix;
}

bool SVGPatternElement::selfHasRelativeLengths() const
{
    return m_x->currentValue()->isRelative()
        || m_y->currentValue()->isRelative()
        || m_width->currentValue()->isRelative()
        || m_height->currentValue()->isRelative();
}

}
<commit_msg>This patch refactors SVGPatternElement::collectPatternAttributes() by extracting the setPatternAttributes logic into a new function. This patch also changes the while loop to be easier to understand and similar to collectGradientAttributes.<commit_after>/*
 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "config.h"

#include "core/svg/SVGPatternElement.h"

#include "XLinkNames.h"
#include "core/rendering/svg/RenderSVGResourcePattern.h"
#include "core/svg/PatternAttributes.h"
#include "core/svg/SVGElementInstance.h"
#include "platform/transforms/AffineTransform.h"

namespace WebCore {

// Animated property definitions
DEFINE_ANIMATED_ENUMERATION(SVGPatternElement, SVGNames::patternUnitsAttr, PatternUnits, patternUnits, SVGUnitTypes::SVGUnitType)
DEFINE_ANIMATED_ENUMERATION(SVGPatternElement, SVGNames::patternContentUnitsAttr, PatternContentUnits, patternContentUnits, SVGUnitTypes::SVGUnitType)
DEFINE_ANIMATED_TRANSFORM_LIST(SVGPatternElement, SVGNames::patternTransformAttr, PatternTransform, patternTransform)
DEFINE_ANIMATED_STRING(SVGPatternElement, XLinkNames::hrefAttr, Href, href)
DEFINE_ANIMATED_PRESERVEASPECTRATIO(SVGPatternElement, SVGNames::preserveAspectRatioAttr, PreserveAspectRatio, preserveAspectRatio)

BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGPatternElement)
    REGISTER_LOCAL_ANIMATED_PROPERTY(patternUnits)
    REGISTER_LOCAL_ANIMATED_PROPERTY(patternContentUnits)
    REGISTER_LOCAL_ANIMATED_PROPERTY(patternTransform)
    REGISTER_LOCAL_ANIMATED_PROPERTY(href)
    REGISTER_LOCAL_ANIMATED_PROPERTY(preserveAspectRatio)
    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGElement)
    REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests)
END_REGISTER_ANIMATED_PROPERTIES

inline SVGPatternElement::SVGPatternElement(Document& document)
    : SVGElement(SVGNames::patternTag, document)
    , m_x(SVGAnimatedLength::create(this, SVGNames::xAttr, SVGLength::create(LengthModeWidth)))
    , m_y(SVGAnimatedLength::create(this, SVGNames::yAttr, SVGLength::create(LengthModeHeight)))
    , m_width(SVGAnimatedLength::create(this, SVGNames::widthAttr, SVGLength::create(LengthModeWidth)))
    , m_height(SVGAnimatedLength::create(this, SVGNames::heightAttr, SVGLength::create(LengthModeHeight)))
    , m_viewBox(SVGAnimatedRect::create(this, SVGNames::viewBoxAttr))
    , m_patternUnits(SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
    , m_patternContentUnits(SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE)
{
    ScriptWrappable::init(this);

    addToPropertyMap(m_x);
    addToPropertyMap(m_y);
    addToPropertyMap(m_width);
    addToPropertyMap(m_height);
    addToPropertyMap(m_viewBox);
    registerAnimatedPropertiesForSVGPatternElement();
}

PassRefPtr<SVGPatternElement> SVGPatternElement::create(Document& document)
{
    return adoptRef(new SVGPatternElement(document));
}

bool SVGPatternElement::isSupportedAttribute(const QualifiedName& attrName)
{
    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
    if (supportedAttributes.isEmpty()) {
        SVGURIReference::addSupportedAttributes(supportedAttributes);
        SVGTests::addSupportedAttributes(supportedAttributes);
        SVGFitToViewBox::addSupportedAttributes(supportedAttributes);
        supportedAttributes.add(SVGNames::patternUnitsAttr);
        supportedAttributes.add(SVGNames::patternContentUnitsAttr);
        supportedAttributes.add(SVGNames::patternTransformAttr);
        supportedAttributes.add(SVGNames::xAttr);
        supportedAttributes.add(SVGNames::yAttr);
        supportedAttributes.add(SVGNames::widthAttr);
        supportedAttributes.add(SVGNames::heightAttr);
    }
    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
}

void SVGPatternElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
{
    SVGParsingError parseError = NoError;

    if (!isSupportedAttribute(name))
        SVGElement::parseAttribute(name, value);
    else if (name == SVGNames::patternUnitsAttr) {
        SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
        if (propertyValue > 0)
            setPatternUnitsBaseValue(propertyValue);
        return;
    } else if (name == SVGNames::patternContentUnitsAttr) {
        SVGUnitTypes::SVGUnitType propertyValue = SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::fromString(value);
        if (propertyValue > 0)
            setPatternContentUnitsBaseValue(propertyValue);
        return;
    } else if (name == SVGNames::patternTransformAttr) {
        SVGTransformList newList;
        newList.parse(value);
        detachAnimatedPatternTransformListWrappers(newList.size());
        setPatternTransformBaseValue(newList);
        return;
    } else if (name == SVGNames::xAttr)
        m_x->setBaseValueAsString(value, AllowNegativeLengths, parseError);
    else if (name == SVGNames::yAttr)
        m_y->setBaseValueAsString(value, AllowNegativeLengths, parseError);
    else if (name == SVGNames::widthAttr)
        m_width->setBaseValueAsString(value, ForbidNegativeLengths, parseError);
    else if (name == SVGNames::heightAttr)
        m_height->setBaseValueAsString(value, ForbidNegativeLengths, parseError);
    else if (SVGURIReference::parseAttribute(name, value)
             || SVGTests::parseAttribute(name, value)
             || SVGFitToViewBox::parseAttribute(this, name, value)) {
    } else
        ASSERT_NOT_REACHED();

    reportAttributeParsingError(parseError, name, value);
}

void SVGPatternElement::svgAttributeChanged(const QualifiedName& attrName)
{
    if (!isSupportedAttribute(attrName)) {
        SVGElement::svgAttributeChanged(attrName);
        return;
    }

    SVGElementInstance::InvalidationGuard invalidationGuard(this);

    if (attrName == SVGNames::xAttr
        || attrName == SVGNames::yAttr
        || attrName == SVGNames::widthAttr
        || attrName == SVGNames::heightAttr)
        updateRelativeLengthsInformation();

    RenderSVGResourceContainer* renderer = toRenderSVGResourceContainer(this->renderer());
    if (renderer)
        renderer->invalidateCacheAndMarkForLayout();
}

void SVGPatternElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
{
    SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);

    if (changedByParser)
        return;

    if (RenderObject* object = renderer())
        object->setNeedsLayout();
}

RenderObject* SVGPatternElement::createRenderer(RenderStyle*)
{
    return new RenderSVGResourcePattern(this);
}

static void setPatternAttributes(const SVGPatternElement* element, PatternAttributes& attributes)
{
    if (!attributes.hasX() && element->hasAttribute(SVGNames::xAttr))
        attributes.setX(element->x()->currentValue());

    if (!attributes.hasY() && element->hasAttribute(SVGNames::yAttr))
        attributes.setY(element->y()->currentValue());

    if (!attributes.hasWidth() && element->hasAttribute(SVGNames::widthAttr))
        attributes.setWidth(element->width()->currentValue());

    if (!attributes.hasHeight() && element->hasAttribute(SVGNames::heightAttr))
        attributes.setHeight(element->height()->currentValue());

    if (!attributes.hasViewBox() && element->hasAttribute(SVGNames::viewBoxAttr) && element->viewBox()->currentValue()->isValid())
        attributes.setViewBox(element->viewBox()->currentValue()->value());

    if (!attributes.hasPreserveAspectRatio() && element->hasAttribute(SVGNames::preserveAspectRatioAttr))
        attributes.setPreserveAspectRatio(element->preserveAspectRatioCurrentValue());

    if (!attributes.hasPatternUnits() && element->hasAttribute(SVGNames::patternUnitsAttr))
        attributes.setPatternUnits(element->patternUnitsCurrentValue());

    if (!attributes.hasPatternContentUnits() && element->hasAttribute(SVGNames::patternContentUnitsAttr))
        attributes.setPatternContentUnits(element->patternContentUnitsCurrentValue());

    if (!attributes.hasPatternTransform() && element->hasAttribute(SVGNames::patternTransformAttr)) {
        AffineTransform transform;
        element->patternTransformCurrentValue().concatenate(transform);
        attributes.setPatternTransform(transform);
    }

    if (!attributes.hasPatternContentElement() && element->childElementCount())
        attributes.setPatternContentElement(element);
}

void SVGPatternElement::collectPatternAttributes(PatternAttributes& attributes) const
{
    HashSet<const SVGPatternElement*> processedPatterns;
    const SVGPatternElement* current = this;

    while (true) {
        setPatternAttributes(current, attributes);
        processedPatterns.add(current);

        // Respect xlink:href, take attributes from referenced element
        Node* refNode = SVGURIReference::targetElementFromIRIString(current->hrefCurrentValue(), document());
        if (refNode && refNode->hasTagName(SVGNames::patternTag)) {
            current = toSVGPatternElement(const_cast<const Node*>(refNode));

            // Cycle detection
            if (processedPatterns.contains(current))
                return;
        } else {
            return;
        }
    }

    ASSERT_NOT_REACHED();
}

AffineTransform SVGPatternElement::localCoordinateSpaceTransform(SVGElement::CTMScope) const
{
    AffineTransform matrix;
    patternTransformCurrentValue().concatenate(matrix);
    return matrix;
}

bool SVGPatternElement::selfHasRelativeLengths() const
{
    return m_x->currentValue()->isRelative()
        || m_y->currentValue()->isRelative()
        || m_width->currentValue()->isRelative()
        || m_height->currentValue()->isRelative();
}

}
<|endoftext|>


<commit_before>#pragma once
//=========================================================================//
/*! @file
    @brief  ARP Protocol @n
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=========================================================================//
#include "net2/net_st.hpp"
#include "common/fixed_fifo.hpp"

namespace net {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ARP クラス
		@param[in]	ETHER	イーサーネット・ドライバー・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template<class ETHER>
	class arp {

		static const uint16_t ARP_REQUEST_WAIT = 200;   ///< 2 sec
		static const uint16_t ARP_REQUEST_NUM  = 5;     ///< 5 times

		struct arp_t {
			uint8_t	head[8];
			uint8_t	src_mac[6];
			uint8_t	src_ipa[4];
			uint8_t dst_mac[6];
			uint8_t dst_ipa[4];
		};

		net_info&	info_;

		typedef utils::fixed_fifo<arp_info, 8> ARP_BUFF;

		ARP_BUFF	arp_buff_;

		ip_adrs		req_ipa_;
		uint16_t	req_wait_;
		uint16_t	req_num_;

		static const uint8_t* get_arp_head7()
		{
			static const uint8_t head[7] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00 };
			return head;
		}

		void dump_(const arp_t& arp)
		{
			utils::format("ARP Header:\n");
			utils::format("  %02X%02X\n")
				% static_cast<uint32_t>(arp.head[0]) % static_cast<uint32_t>(arp.head[1]);
			utils::format("  %02X%02X\n")
				% static_cast<uint32_t>(arp.head[2]) % static_cast<uint32_t>(arp.head[3]);
			utils::format("  %02X%02X\n")
				% static_cast<uint32_t>(arp.head[4]) % static_cast<uint32_t>(arp.head[5]);
			utils::format("  %02X%02X\n")
				% static_cast<uint32_t>(arp.head[6]) % static_cast<uint32_t>(arp.head[7]);
			utils::format("  src: %s, %s\n") % tools::mac_str(arp.src_mac) % tools::ip_str(arp.src_ipa);
			utils::format("  dst: %s, %s\n") % tools::mac_str(arp.dst_mac) % tools::ip_str(arp.dst_ipa);
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	info	ネット情報
		*/
		//-----------------------------------------------------------------//
		arp(net_info& info) : info_(info), req_ipa_(), req_wait_(0), req_num_(0)
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief  パース
			@param[in]	eth		イーサーネット・ドライバー
			@param[in]	h		ヘッダー
			@param[in]	top		先頭ポインター
			@param[in]	len		長さ
		*/
		//-----------------------------------------------------------------//
		bool parse(ETHER& eth, const eth_h& h, const void* top, int32_t len)
		{
			if(static_cast<size_t>(len) < sizeof(arp_t)) {
				return false;
			}

			const arp_t& r = *static_cast<const arp_t*>(top);
			if(std::memcmp(get_arp_head7(), r.head, 7) != 0) {
				return false;
			}

			if(tools::check_brodcast_mac(h.get_dst()) && r.head[7] == 0x01) {  // ARP Request
				if(arp_buff_.length() < (arp_buff_.size() - 1)) {
					arp_info a;
					a.ipa.set(r.src_ipa[0], r.src_ipa[1], r.src_ipa[2], r.src_ipa[3]);
					std::memcpy(a.mac, r.src_mac, 6);
					arp_buff_.put(a);
				}
			} else if(r.head[7] == 0x02) {  // ARP Response
				// IP/MAC の収集
				if(arp_buff_.length() < (arp_buff_.size() - 2)) {
					arp_info a;
					a.ipa.set(r.src_ipa[0], r.src_ipa[1], r.src_ipa[2], r.src_ipa[3]);
					std::memcpy(a.mac, r.src_mac, 6);
					arp_buff_.put(a);
					a.ipa.set(r.dst_ipa[0], r.dst_ipa[1], r.dst_ipa[2], r.dst_ipa[3]);
					std::memcpy(a.mac, r.dst_mac, 6);
					arp_buff_.put(a);
				}
				return false;
			} else {
				return false;
			}

			ip_adrs ipa(r.dst_ipa[0], r.dst_ipa[1], r.dst_ipa[2], r.dst_ipa[3]);
			if(info_.ip != ipa) {
				return false;
			}

//			utils::format("ARP: src: %s, dst: %s\n")
//				% tools::ip_str(r.src_ipa)
//				% tools::ip_str(r.dst_ipa);
			void* dst;
			uint16_t dlen;
			if(eth.send_buff(&dst, dlen) != 0) {
				utils::format("ARP: ether send_buff error\n");
				return false;
			}

			eth_h& eh = *static_cast<eth_h*>(dst);
			eh.set_dst(h.get_src());
			eh.set_src(info_.mac);
			eh.set_type(eth_type::ARP);

   			arp_t& arp = *static_cast<arp_t*>(eth_h::next_ptr(dst));
			std::memcpy(arp.head, get_arp_head7(), 7);
			arp.head[7] = 0x02;
			std::memcpy(arp.src_mac, info_.mac, 6);
			std::memcpy(arp.src_ipa, info_.ip.get(), 4);
			std::memcpy(arp.dst_mac, r.src_mac, 6);
			std::memcpy(arp.dst_ipa, r.src_ipa, 4);

//			dump(eh);
//			dump_(arp);

			eth.send(sizeof(eth_h) + sizeof(arp_t));

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  リクエスト
			@param[in]	eth		イーサーネット・ドライバー
			@param[in]	ipa		リクエストする IP アドレス
			@return 正常終了なら「true」
		*/
		//-----------------------------------------------------------------//
		bool request(ETHER& eth, const ip_adrs& ipa)
		{
			void* dst;
			uint16_t dlen;
			if(eth.send_buff(&dst, dlen) != 0) {
				utils::format("ARP: ether send_buff error\n");
				return false;
			}

			eth_h& eh = *static_cast<eth_h*>(dst);
			eh.set_dst(tools::get_brodcast_mac());
			eh.set_src(info_.mac);
			eh.set_type(eth_type::ARP);

   			arp_t& arp = *static_cast<arp_t*>(eth_h::next_ptr(dst));
			std::memcpy(arp.head, get_arp_head7(), 7);
			arp.head[7] = 0x01;  // request
			std::memcpy(arp.src_mac, info_.mac, 6);
			std::memcpy(arp.src_ipa, info_.ip.get(), 4);
			std::memset(arp.dst_mac, 0x00, 6);
			std::memcpy(arp.dst_ipa, ipa.get(), 4);

			eth.send(sizeof(eth_h) + sizeof(arp_t));

			req_ipa_   = ipa;
			req_wait_  = ARP_REQUEST_WAIT;
			req_num_   = ARP_REQUEST_NUM;
			utils::format("ARP request: %s\n") % ipa.c_str();

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  サービス
			@param[in]	eth		イーサーネット・ドライバー
		*/
		//-----------------------------------------------------------------//
		void service(ETHER& eth)
		{
			while(arp_buff_.length() > 0) {
				const auto a = arp_buff_.get();
				info_.cash.insert(a.ipa, a.mac);
			}

			if(req_wait_) {
				--req_wait_;
			} else if(req_num_) {
				--req_num_;
				auto n = info_.cash.lookup(req_ipa_);
				if(n >= info_.cash.capacity()) {
					req_wait_ = ARP_REQUEST_WAIT;
					request(eth, req_ipa_);
				}
			}
		}
	};
}
<commit_msg>exclusive control for buffer<commit_after>#pragma once
//=========================================================================//
/*! @file
    @brief  ARP Protocol @n
			Copyright 2017 Kunihito Hiramatsu
    @author 平松邦仁 (hira@rvf-rc45.net)
*/
//=========================================================================//
#include "net2/net_st.hpp"
#include "common/fixed_fifo.hpp"

namespace net {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  ARP クラス
		@param[in]	ETHER	イーサーネット・ドライバー・クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template<class ETHER>
	class arp {

		static const uint16_t ARP_REQUEST_WAIT = 200;   ///< 2 sec
		static const uint16_t ARP_REQUEST_NUM  = 5;     ///< 5 times

		struct arp_h {
			uint8_t	head[8];
			uint8_t	src_mac[6];
			uint8_t	src_ipa[4];
			uint8_t dst_mac[6];
			uint8_t dst_ipa[4];
		} __attribute__((__packed__));

		net_info&	info_;

		typedef utils::fixed_fifo<arp_info, 8> ARP_BUFF;
		ARP_BUFF	arp_buff_;

		struct arp_send_t {
			eth_h	eh_;
			arp_h	arp_;
		} __attribute__((__packed__));
		typedef utils::fixed_fifo<arp_send_t, 4> ARP_SEND;
		ARP_SEND	arp_send_;

		ip_adrs		req_ipa_;
		uint16_t	req_wait_;
		uint16_t	req_num_;

		static const uint8_t* get_arp_head7()
		{
			static const uint8_t head[7] = { 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00 };
			return head;
		}

		void dump_(const arp_h& arp)
		{
			utils::format("ARP Header:\n");
			utils::format("  %02X%02X\n")
				% static_cast<uint32_t>(arp.head[0]) % static_cast<uint32_t>(arp.head[1]);
			utils::format("  %02X%02X\n")
				% static_cast<uint32_t>(arp.head[2]) % static_cast<uint32_t>(arp.head[3]);
			utils::format("  %02X%02X\n")
				% static_cast<uint32_t>(arp.head[4]) % static_cast<uint32_t>(arp.head[5]);
			utils::format("  %02X%02X\n")
				% static_cast<uint32_t>(arp.head[6]) % static_cast<uint32_t>(arp.head[7]);
			utils::format("  src: %s, %s\n") % tools::mac_str(arp.src_mac) % tools::ip_str(arp.src_ipa);
			utils::format("  dst: %s, %s\n") % tools::mac_str(arp.dst_mac) % tools::ip_str(arp.dst_ipa);
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
			@param[in]	info	ネット情報
		*/
		//-----------------------------------------------------------------//
		arp(net_info& info) : info_(info), req_ipa_(), req_wait_(0), req_num_(0)
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief  プロセス @n
					※割り込み外から呼ぶ事は禁止
			@param[in]	eth		イーサーネット・ドライバー
			@param[in]	h		ヘッダー
			@param[in]	top		先頭ポインター
			@param[in]	len		長さ
		*/
		//-----------------------------------------------------------------//
		bool process(ETHER& eth, const eth_h& h, const void* top, int32_t len)
		{
			bool ret = false;
			if(static_cast<size_t>(len) < sizeof(arp_h)) {
				goto process_end;
			}

			{
				const arp_h& r = *static_cast<const arp_h*>(top);
				if(std::memcmp(get_arp_head7(), r.head, 7) != 0) {
					goto process_end;
				}

				if(tools::check_brodcast_mac(h.get_dst()) && r.head[7] == 0x01) {  // ARP Request
					if(arp_buff_.length() < (arp_buff_.size() - 1)) {
						arp_info& a = arp_buff_.put_at();
						a.ipa.set(r.src_ipa[0], r.src_ipa[1], r.src_ipa[2], r.src_ipa[3]);
						std::memcpy(a.mac, r.src_mac, 6);
						arp_buff_.put_go();
					}
				} else if(r.head[7] == 0x02) {  // ARP Response
					// IP/MAC の収集
					if(arp_buff_.length() < (arp_buff_.size() - 2)) {
						{
							arp_info& a = arp_buff_.put_at();
							a.ipa.set(r.src_ipa[0], r.src_ipa[1], r.src_ipa[2], r.src_ipa[3]);
							std::memcpy(a.mac, r.src_mac, 6);
							arp_buff_.put_go();
						}
						{
							arp_info& a = arp_buff_.put_at();
							a.ipa.set(r.dst_ipa[0], r.dst_ipa[1], r.dst_ipa[2], r.dst_ipa[3]);
							std::memcpy(a.mac, r.dst_mac, 6);
							arp_buff_.put_go();
						}
					}
					goto process_end;
				} else {
					goto process_end;
				}

				ip_adrs ipa(r.dst_ipa[0], r.dst_ipa[1], r.dst_ipa[2], r.dst_ipa[3]);
				if(info_.ip != ipa) {
					goto process_end;
				}

//			utils::format("ARP: src: %s, dst: %s\n")
//				% tools::ip_str(r.src_ipa)
//				% tools::ip_str(r.dst_ipa);
				void* dst;
				uint16_t dlen;
				if(eth.send_buff(&dst, dlen) != 0) {
					utils::format("ARP: ether send_buff error\n");
					goto process_end;
				}

				eth_h& eh = *static_cast<eth_h*>(dst);
				eh.set_dst(h.get_src());
				eh.set_src(info_.mac);
				eh.set_type(eth_type::ARP);

   				arp_h& arp = *static_cast<arp_h*>(eth_h::next_ptr(dst));
				std::memcpy(arp.head, get_arp_head7(), 7);
				arp.head[7] = 0x02;
				std::memcpy(arp.src_mac, info_.mac, 6);
				std::memcpy(arp.src_ipa, info_.ip.get(), 4);
				std::memcpy(arp.dst_mac, r.src_mac, 6);
				std::memcpy(arp.dst_ipa, r.src_ipa, 4);

//			dump(eh);
//			dump_(arp);

				eth.send(sizeof(eth_h) + sizeof(arp_h));
			}
			ret = true;

		process_end:

			while(arp_send_.length() > 0) {
				const arp_send_t& t = arp_send_.get();

				void* dst;
				uint16_t dlen;
				if(eth.send_buff(&dst, dlen) != 0) {
					utils::format("ARP: ether send_buff error\n");
					return false;
				}
				std::memcpy(dst, &t, sizeof(arp_send_t));
				eth.send(sizeof(arp_send_t));
			}

			return ret;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  リクエスト
			@param[in]	ipa		リクエストする IP アドレス
			@return 正常終了なら「true」
		*/
		//-----------------------------------------------------------------//
		bool request(const ip_adrs& ipa)
		{
			arp_send_t& t = arp_send_.put_at();

			t.eh_.set_dst(tools::get_brodcast_mac());
			t.eh_.set_src(info_.mac);
			t.eh_.set_type(eth_type::ARP);

			std::memcpy(t.arp_.head, get_arp_head7(), 7);
			t.arp_.head[7] = 0x01;  // request
			std::memcpy(t.arp_.src_mac, info_.mac, 6);
			std::memcpy(t.arp_.src_ipa, info_.ip.get(), 4);
			std::memset(t.arp_.dst_mac, 0x00, 6);
			std::memcpy(t.arp_.dst_ipa, ipa.get(), 4);

			arp_send_.put_go();

			req_ipa_   = ipa;
			req_wait_  = ARP_REQUEST_WAIT;
			req_num_   = ARP_REQUEST_NUM;
			utils::format("ARP request: %s\n") % ipa.c_str();

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  サービス
		*/
		//-----------------------------------------------------------------//
		void service()
		{
			while(arp_buff_.length() > 0) {
				const arp_info& a = arp_buff_.get_at();
				info_.cash.insert(a.ipa, a.mac);
				arp_buff_.get_go();
			}

			if(req_wait_) {
				--req_wait_;
			} else if(req_num_) {
				--req_num_;
				auto n = info_.cash.lookup(req_ipa_);
				if(n >= info_.cash.capacity()) {
					req_wait_ = ARP_REQUEST_WAIT;
					request(req_ipa_);
				}
			}
		}
	};
}
<|endoftext|>


<commit_before>/*
 * MIT License

 * Copyright (c) 2016 - 2018 Thomas Prescher

 * 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.
 */

#pragma once

#include "heap_config.hpp"

class memory
{
public:
    virtual ~memory() {}

    virtual size_t base() const = 0;
    virtual size_t size() const = 0;
    virtual size_t end()  const = 0;
};

class fixed_memory : public memory
{
private:
    size_t base_;
    size_t size_;

public:
    fixed_memory(size_t base, size_t size)
        : base_(base)
        , size_(size)
    {
    }

    virtual size_t base() const { return base_; }
    virtual size_t size() const { return size_; };
    virtual size_t end()  const { return base_ + size_; }
};

static constexpr size_t HEAP_MIN_ALIGNMENT = 16;

template<size_t ALIGNMENT = HEAP_MIN_ALIGNMENT>
class first_fit_heap
{
private:
    static constexpr size_t min_alignment() { return HEAP_MIN_ALIGNMENT; }

    struct empty {};
    template <size_t, bool, class T>
    struct align_helper : public T {};

    template <size_t SIZE, class T>
    struct HEAP_PACKED align_helper<SIZE, true, T> : public T {
        char align_chars[SIZE - min_alignment()];
    };

    template <size_t MIN, size_t SIZE>
    using prepend_alignment_if_greater = align_helper<SIZE, (SIZE > MIN), empty>;

    class header_free;
    class header_used;

    class footer {
    public:
        size_t size() const { return s; }

        void size(size_t size) { s = size; }

        header_free* header() {
            return reinterpret_cast<header_free*>(reinterpret_cast<char *>(this) + sizeof(footer) - size() - sizeof(header_used));
        }

    private:
        size_t s;
    };

    class HEAP_PACKED header_used : private prepend_alignment_if_greater<16, ALIGNMENT>
    {
    private:
        enum {
            PREV_FREE_MASK = ~(1ul << (sizeof(size_t) * 8 - 1)),
            THIS_FREE_MASK = ~(1ul << (sizeof(size_t) * 8 - 2)),
            SIZE_MASK      = (~PREV_FREE_MASK) | (~THIS_FREE_MASK),
            CANARY_VALUE   = 0x1337133713371337ul,
        };

        size_t raw {0};
        volatile size_t canary {CANARY_VALUE};

    public:
        header_used(const size_t size_) { size(size_); }

        size_t size() const { return raw & ~SIZE_MASK; }

        void size(size_t s)
        {
            ASSERT_HEAP((s & ~SIZE_MASK) == s);
            raw &= SIZE_MASK;
            raw |= s & ~SIZE_MASK;
        }

        bool prev_free() const { return raw & ~PREV_FREE_MASK; }

        void prev_free(bool val)
        {
            raw &= PREV_FREE_MASK;
            raw |= (~PREV_FREE_MASK) * val;
        }

        bool is_free() const { return raw & ~THIS_FREE_MASK; }

        void is_free(bool val)
        {
            raw &= THIS_FREE_MASK;
            raw |= (~THIS_FREE_MASK) * val;
        }

        bool canary_alive() { return canary == CANARY_VALUE; }

        header_used *following_block(const memory &mem)
        {
            auto *following = reinterpret_cast<header_used *>(reinterpret_cast<char *>(this) + sizeof(header_used) + size());
            if (reinterpret_cast<size_t>(following) >= mem.end()) {
                return nullptr;
            }

            return following;
        }

        header_used *preceding_block(const memory& mem)
        {
            if (not prev_free()) {
                return nullptr;
            }

            footer *prev_footer = reinterpret_cast<footer *>(reinterpret_cast<char *>(this) - sizeof(footer));

            ASSERT_HEAP(reinterpret_cast<size_t>(prev_footer) > mem.base());

            return prev_footer->header();
        }

        void *data_ptr() { return this+1; }
    };

    class HEAP_PACKED header_free : public header_used
    {
    public:
        header_free(const size_t size) : header_used(size)
        {
            update_footer();
            this->is_free(true);
        }

        header_free *next() const { return next_; }
        void         next(header_free *val) { next_ = val; }

        footer *get_footer()
        {
            return reinterpret_cast<footer *>(reinterpret_cast<char *>(this) + sizeof(header_used) + this->size() - sizeof(footer));
        }

        void update_footer()
        {
            get_footer()->size(this->size());
        }

        header_free *next_ {nullptr};
    };

    class free_list_container
    {
    public:
        free_list_container(memory &mem_, header_free *root) : mem(mem_), list(root)
        {
            ASSERT_HEAP(ALIGNMENT != 0);
            ASSERT_HEAP(ALIGNMENT >= min_alignment());
            ASSERT_HEAP((ALIGNMENT & (ALIGNMENT - 1)) == 0);
            ASSERT_HEAP(sizeof(header_used) == ALIGNMENT);
            ASSERT_HEAP(mem.size() != 0);
            ASSERT_HEAP((mem.base() & (ALIGNMENT - 1)) == 0);
            ASSERT_HEAP((mem.base() + mem.size()) > mem.base());
        }

        class iterator
        {
        public:
            iterator(header_free *block_ = nullptr) : block(block_) {}

            iterator &operator++()
            {
                block = block->next();
                ASSERT_HEAP(block ? block->canary_alive() : true);
                return *this;
            }

            header_free *operator*() const { return block; }

            bool operator!=(const iterator &other) const { return block != other.block; }

            bool operator==(const iterator &other) const { return not operator!=(other); }

        private:
            header_free *block;
        };

        iterator begin() const { return iterator(list); }
        iterator end()   const { return iterator(); }

    private:
        iterator position_for(header_free *val)
        {
            for (auto elem : *this) {
                if (not elem->next() or (elem->next() > val)) {
                    return elem < val ? iterator(elem) : iterator();
                }
            }

            return end();
        }

        iterator insert_after(header_free *val, iterator other)
        {
            if (not val) {
                return {};
            }

            ASSERT_HEAP(val > *other);

            if (other == end()) {
                // insert at list head
                val->next(list);
                val->is_free(true);
                val->update_footer();
                list = val;
            } else {
                // insert block into chain
                auto *tmp = (*other)->next();
                val->next(tmp);
                val->is_free(true);
                val->update_footer();

                ASSERT_HEAP(val != *other);
                (*other)->next(val);
            }

            // update meta data of surrounding blocks
            auto       *following = val->following_block(mem);
            const auto *preceding = val->preceding_block(mem);

            if (following) {
                following->prev_free(true);
            }

            if (preceding and preceding->is_free()) {
                val->prev_free(true);
            }

            return {val};
        }

        iterator try_merge_back(iterator it)
        {
            auto *following = (*it)->following_block(mem);

            if (following and following->is_free()) {
                auto *following_free = static_cast<header_free*>(following);
                (*it)->next(following_free->next());
                (*it)->size((*it)->size() + following_free->size() + sizeof(header_used));
                (*it)->update_footer();
            }

            return it;
        }

        iterator try_merge_front(iterator it)
        {
            if (not (*it)->prev_free()) {
                return it;
            }

            auto *preceding = static_cast<header_free *>((*it)->preceding_block(mem));
            if (not preceding) {
                return it;
            }

            ASSERT_HEAP(preceding->is_free());
            return try_merge_back({preceding});
        }

        static constexpr size_t min_block_size() { return sizeof(header_free) - sizeof(header_used) + sizeof(footer); }

        size_t align(size_t size) const
        {
            size_t real_size {(size + ALIGNMENT - 1) & ~(ALIGNMENT - 1)};
            return HEAP_MAX(min_block_size(), real_size);
        }

        bool fits(header_free &block, size_t size) const
        {
            ASSERT_HEAP(size >= min_block_size());
            return block.size() >= size;
        }

        iterator first_free(size_t size, iterator &before) const
        {
            iterator before_ = end();

            for (auto elem : *this) {
                if (fits(*elem, size)) {
                    before = before_;
                    return {elem};
                }
                before_ = iterator(elem);
            }

            return {};
        }

    public:
        iterator insert(header_free *val)
        {
            auto pos  = position_for(val);
            auto elem = insert_after(val, pos);
            return try_merge_front(try_merge_back(elem));
        }

        header_used *alloc(size_t size)
        {
            size = HEAP_MAX(size, ALIGNMENT);
            size = align(size);

            iterator prev;
            auto it = first_free(size, prev);

            if (it == end()) {
                return nullptr;
            }

            auto  &block          = **it;
            size_t size_remaining = block.size() - size;

            if (size_remaining < (sizeof(header_free) + sizeof(footer))) {
                // remaining size cannot hold another block, use entire space
                size += size_remaining;
            } else {
                // split block into two
                block.size(size);
                block.update_footer();
                auto *new_block = new (block.following_block(mem)) header_free(size_remaining - sizeof(header_used));
                new_block->next(block.next());
                new_block->prev_free(true);
                block.next(new_block);
            }

            if (*prev) {
                (*prev)->next(block.next());
            } else {
                list = block.next();
            }

            auto *following = block.following_block(mem);
            if (following) {
                following->prev_free(false);
            }

            block.is_free(false);
            return █
        }

        bool ptr_in_range(void *p)
        {
            return reinterpret_cast<size_t>(p) >= mem.base() and reinterpret_cast<size_t>(p) < mem.end();
        }

    private:
        memory &mem;
        header_free *list;
    };

private:
    free_list_container free_list;

public:
    first_fit_heap(memory &mem_) : free_list(mem_, new(reinterpret_cast<void *>(mem_.base())) header_free(mem_.size() - sizeof(header_used)))
    {
    }

    void *alloc(size_t size)
    {
        auto *block = free_list.alloc(size);
        return block ? block->data_ptr() : nullptr;
    }

    void free(void *p)
    {
        header_free *header {reinterpret_cast<header_free *>(reinterpret_cast<char *>(p) - sizeof(header_used))};

        if (not p or not free_list.ptr_in_range(header)) {
            return;
        }

        ASSERT_HEAP(header->canary_alive());
        ASSERT_HEAP(not header->is_free());

        free_list.insert(header);
    }

    size_t num_blocks() const
    {
        size_t cnt {0};

        for (auto HEAP_UNUSED elem : free_list) {
            cnt++;
        }

        return cnt;
    }

    size_t free_mem() const
    {
        size_t size {0};

        for (auto  elem : free_list) {
            size += elem->size();
        }

        return size;
    }

    constexpr size_t alignment() const { return ALIGNMENT; }
};
<commit_msg>add memory reference<commit_after>/*
 * MIT License

 * Copyright (c) 2016 - 2018 Thomas Prescher

 * 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.
 */

#pragma once

#include "heap_config.hpp"

class memory
{
public:
    virtual ~memory() {}

    virtual size_t base() const = 0;
    virtual size_t size() const = 0;
    virtual size_t end()  const = 0;
};

class fixed_memory : public memory
{
private:
    size_t base_;
    size_t size_;

public:
    fixed_memory(size_t base, size_t size)
        : base_(base)
        , size_(size)
    {
    }

    virtual size_t base() const { return base_; }
    virtual size_t size() const { return size_; };
    virtual size_t end()  const { return base_ + size_; }
};

static constexpr size_t HEAP_MIN_ALIGNMENT = 16;

template<size_t ALIGNMENT = HEAP_MIN_ALIGNMENT>
class first_fit_heap
{
private:
    static constexpr size_t min_alignment() { return HEAP_MIN_ALIGNMENT; }

    struct empty {};
    template <size_t, bool, class T>
    struct align_helper : public T {};

    template <size_t SIZE, class T>
    struct HEAP_PACKED align_helper<SIZE, true, T> : public T {
        char align_chars[SIZE - min_alignment()];
    };

    template <size_t MIN, size_t SIZE>
    using prepend_alignment_if_greater = align_helper<SIZE, (SIZE > MIN), empty>;

    class header_free;
    class header_used;

    class footer {
    public:
        size_t size() const { return s; }

        void size(size_t size) { s = size; }

        header_free* header() {
            return reinterpret_cast<header_free*>(reinterpret_cast<char *>(this) + sizeof(footer) - size() - sizeof(header_used));
        }

    private:
        size_t s;
    };

    class HEAP_PACKED header_used : private prepend_alignment_if_greater<16, ALIGNMENT>
    {
    private:
        enum {
            PREV_FREE_MASK = ~(1ul << (sizeof(size_t) * 8 - 1)),
            THIS_FREE_MASK = ~(1ul << (sizeof(size_t) * 8 - 2)),
            SIZE_MASK      = (~PREV_FREE_MASK) | (~THIS_FREE_MASK),
            CANARY_VALUE   = 0x1337133713371337ul,
        };

        size_t raw {0};
        volatile size_t canary {CANARY_VALUE};

    public:
        header_used(const size_t size_) { size(size_); }

        size_t size() const { return raw & ~SIZE_MASK; }

        void size(size_t s)
        {
            ASSERT_HEAP((s & ~SIZE_MASK) == s);
            raw &= SIZE_MASK;
            raw |= s & ~SIZE_MASK;
        }

        bool prev_free() const { return raw & ~PREV_FREE_MASK; }

        void prev_free(bool val)
        {
            raw &= PREV_FREE_MASK;
            raw |= (~PREV_FREE_MASK) * val;
        }

        bool is_free() const { return raw & ~THIS_FREE_MASK; }

        void is_free(bool val)
        {
            raw &= THIS_FREE_MASK;
            raw |= (~THIS_FREE_MASK) * val;
        }

        bool canary_alive() { return canary == CANARY_VALUE; }

        header_used *following_block(const memory &mem)
        {
            auto *following = reinterpret_cast<header_used *>(reinterpret_cast<char *>(this) + sizeof(header_used) + size());
            if (reinterpret_cast<size_t>(following) >= mem.end()) {
                return nullptr;
            }

            return following;
        }

        header_used *preceding_block(const memory& mem)
        {
            if (not prev_free()) {
                return nullptr;
            }

            footer *prev_footer = reinterpret_cast<footer *>(reinterpret_cast<char *>(this) - sizeof(footer));

            ASSERT_HEAP(reinterpret_cast<size_t>(prev_footer) > mem.base());

            return prev_footer->header();
        }

        void *data_ptr() { return this+1; }
    };

    class HEAP_PACKED header_free : public header_used
    {
    public:
        header_free(const size_t size) : header_used(size)
        {
            update_footer();
            this->is_free(true);
        }

        header_free *next() const { return next_; }
        void         next(header_free *val) { next_ = val; }

        footer *get_footer()
        {
            return reinterpret_cast<footer *>(reinterpret_cast<char *>(this) + sizeof(header_used) + this->size() - sizeof(footer));
        }

        void update_footer()
        {
            get_footer()->size(this->size());
        }

        header_free *next_ {nullptr};
    };

    class free_list_container
    {
    public:
        free_list_container(memory &mem_, header_free *root) : mem(mem_), list(root)
        {
            ASSERT_HEAP(ALIGNMENT != 0);
            ASSERT_HEAP(ALIGNMENT >= min_alignment());
            ASSERT_HEAP((ALIGNMENT & (ALIGNMENT - 1)) == 0);
            ASSERT_HEAP(sizeof(header_used) == ALIGNMENT);
            ASSERT_HEAP(mem.size() != 0);
            ASSERT_HEAP((mem.base() & (ALIGNMENT - 1)) == 0);
            ASSERT_HEAP((mem.base() + mem.size()) > mem.base());
        }

        class iterator
        {
        public:
            iterator(header_free *block_ = nullptr) : block(block_) {}

            iterator &operator++()
            {
                block = block->next();
                ASSERT_HEAP(block ? block->canary_alive() : true);
                return *this;
            }

            header_free *operator*() const { return block; }

            bool operator!=(const iterator &other) const { return block != other.block; }

            bool operator==(const iterator &other) const { return not operator!=(other); }

        private:
            header_free *block;
        };

        iterator begin() const { return iterator(list); }
        iterator end()   const { return iterator(); }

    private:
        iterator position_for(header_free *val)
        {
            for (auto elem : *this) {
                if (not elem->next() or (elem->next() > val)) {
                    return elem < val ? iterator(elem) : iterator();
                }
            }

            return end();
        }

        iterator insert_after(header_free *val, iterator other)
        {
            if (not val) {
                return {};
            }

            ASSERT_HEAP(val > *other);

            if (other == end()) {
                // insert at list head
                val->next(list);
                val->is_free(true);
                val->update_footer();
                list = val;
            } else {
                // insert block into chain
                auto *tmp = (*other)->next();
                val->next(tmp);
                val->is_free(true);
                val->update_footer();

                ASSERT_HEAP(val != *other);
                (*other)->next(val);
            }

            // update meta data of surrounding blocks
            auto       *following = val->following_block(mem);
            const auto *preceding = val->preceding_block(mem);

            if (following) {
                following->prev_free(true);
            }

            if (preceding and preceding->is_free()) {
                val->prev_free(true);
            }

            return {val};
        }

        iterator try_merge_back(iterator it)
        {
            auto *following = (*it)->following_block(mem);

            if (following and following->is_free()) {
                auto *following_free = static_cast<header_free*>(following);
                (*it)->next(following_free->next());
                (*it)->size((*it)->size() + following_free->size() + sizeof(header_used));
                (*it)->update_footer();
            }

            return it;
        }

        iterator try_merge_front(iterator it)
        {
            if (not (*it)->prev_free()) {
                return it;
            }

            auto *preceding = static_cast<header_free *>((*it)->preceding_block(mem));
            if (not preceding) {
                return it;
            }

            ASSERT_HEAP(preceding->is_free());
            return try_merge_back({preceding});
        }

        static constexpr size_t min_block_size() { return sizeof(header_free) - sizeof(header_used) + sizeof(footer); }

        size_t align(size_t size) const
        {
            size_t real_size {(size + ALIGNMENT - 1) & ~(ALIGNMENT - 1)};
            return HEAP_MAX(min_block_size(), real_size);
        }

        bool fits(header_free &block, size_t size) const
        {
            ASSERT_HEAP(size >= min_block_size());
            return block.size() >= size;
        }

        iterator first_free(size_t size, iterator &before) const
        {
            iterator before_ = end();

            for (auto elem : *this) {
                if (fits(*elem, size)) {
                    before = before_;
                    return {elem};
                }
                before_ = iterator(elem);
            }

            return {};
        }

    public:
        iterator insert(header_free *val)
        {
            auto pos  = position_for(val);
            auto elem = insert_after(val, pos);
            return try_merge_front(try_merge_back(elem));
        }

        header_used *alloc(size_t size)
        {
            size = HEAP_MAX(size, ALIGNMENT);
            size = align(size);

            iterator prev;
            auto it = first_free(size, prev);

            if (it == end()) {
                return nullptr;
            }

            auto  &block          = **it;
            size_t size_remaining = block.size() - size;

            if (size_remaining < (sizeof(header_free) + sizeof(footer))) {
                // remaining size cannot hold another block, use entire space
                size += size_remaining;
            } else {
                // split block into two
                block.size(size);
                block.update_footer();
                auto *new_block = new (block.following_block(mem)) header_free(size_remaining - sizeof(header_used));
                new_block->next(block.next());
                new_block->prev_free(true);
                block.next(new_block);
            }

            if (*prev) {
                (*prev)->next(block.next());
            } else {
                list = block.next();
            }

            auto *following = block.following_block(mem);
            if (following) {
                following->prev_free(false);
            }

            block.is_free(false);
            return █
        }

        bool ptr_in_range(void *p)
        {
            return reinterpret_cast<size_t>(p) >= mem.base() and reinterpret_cast<size_t>(p) < mem.end();
        }

    private:
        memory &mem;
        header_free *list;
    };

private:
    memory &mem;

    free_list_container free_list;

public:
    first_fit_heap(memory &mem_) : mem(mem_), free_list(mem_, new(reinterpret_cast<void *>(mem_.base())) header_free(mem_.size() - sizeof(header_used)))
    {
    }

    void *alloc(size_t size)
    {
        auto *block = free_list.alloc(size);
        return block ? block->data_ptr() : nullptr;
    }

    void free(void *p)
    {
        header_free *header {reinterpret_cast<header_free *>(reinterpret_cast<char *>(p) - sizeof(header_used))};

        if (not p or not free_list.ptr_in_range(header)) {
            return;
        }

        ASSERT_HEAP(header->canary_alive());
        ASSERT_HEAP(not header->is_free());

        free_list.insert(header);
    }

    size_t num_blocks() const
    {
        size_t cnt {0};

        for (auto HEAP_UNUSED elem : free_list) {
            cnt++;
        }

        return cnt;
    }

    size_t free_mem() const
    {
        size_t size {0};

        for (auto  elem : free_list) {
            size += elem->size();
        }

        return size;
    }

    constexpr size_t alignment() const { return ALIGNMENT; }
};
<|endoftext|>


<commit_before>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Rosetta/Games/GameManager.hpp>

namespace RosettaStone
{
void GameManager::ProcessNextStep(Game& game, Step step)
{
    switch (step)
    {
        case Step::BEGIN_FIRST:
            game.step = step;
            game.BeginFirst();
            break;
        case Step::BEGIN_SHUFFLE:
            game.step = step;
            game.BeginShuffle();
            break;
        case Step::BEGIN_DRAW:
            game.step = step;
            game.BeginDraw();
            break;
        case Step::BEGIN_MULLIGAN:
            game.step = step;
            game.BeginMulligan();
            break;
        case Step::MAIN_BEGIN:
            game.step = step;
            game.MainBegin();
            break;
        case Step::MAIN_READY:
            game.step = step;
            game.MainReady();
            break;
        case Step::MAIN_START_TRIGGERS:
            game.step = step;
            game.MainStartTriggers();
            break;
        case Step::MAIN_RESOURCE:
            game.step = step;
            game.MainResource();
            break;
        case Step::MAIN_DRAW:
            game.step = step;
            game.MainDraw();
            break;
        case Step::MAIN_START:
            game.step = step;
            game.MainStart();
            break;
        case Step::MAIN_ACTION:
            game.step = step;
            break;
        case Step::MAIN_COMBAT:
            break;
        case Step::MAIN_END:
            game.step = step;
            game.MainEnd();
            break;
        case Step::MAIN_CLEANUP:
            game.step = step;
            game.MainCleanUp();
            break;
        case Step::MAIN_NEXT:
            game.step = step;
            game.MainNext();
            break;
        case Step::FINAL_WRAPUP:
            game.FinalWrapUp();
            break;
        case Step::FINAL_GAMEOVER:
            game.FinalGameOver();
            break;
        default:
            break;
    }
}
}  // namespace RosettaStone
<commit_msg>feat(GameManager): Add MainAction<commit_after>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Rosetta/Games/GameManager.hpp>

namespace RosettaStone
{
void GameManager::ProcessNextStep(Game& game, Step step)
{
    switch (step)
    {
        case Step::BEGIN_FIRST:
            game.step = step;
            game.BeginFirst();
            break;
        case Step::BEGIN_SHUFFLE:
            game.step = step;
            game.BeginShuffle();
            break;
        case Step::BEGIN_DRAW:
            game.step = step;
            game.BeginDraw();
            break;
        case Step::BEGIN_MULLIGAN:
            game.step = step;
            game.BeginMulligan();
            break;
        case Step::MAIN_BEGIN:
            game.step = step;
            game.MainBegin();
            break;
        case Step::MAIN_READY:
            game.step = step;
            game.MainReady();
            break;
        case Step::MAIN_START_TRIGGERS:
            game.step = step;
            game.MainStartTriggers();
            break;
        case Step::MAIN_RESOURCE:
            game.step = step;
            game.MainResource();
            break;
        case Step::MAIN_DRAW:
            game.step = step;
            game.MainDraw();
            break;
        case Step::MAIN_START:
            game.step = step;
            game.MainStart();
            break;
        case Step::MAIN_ACTION:
            game.step = step;
            game.MainAction();
            break;
        case Step::MAIN_COMBAT:
            break;
        case Step::MAIN_END:
            game.step = step;
            game.MainEnd();
            break;
        case Step::MAIN_CLEANUP:
            game.step = step;
            game.MainCleanUp();
            break;
        case Step::MAIN_NEXT:
            game.step = step;
            game.MainNext();
            break;
        case Step::FINAL_WRAPUP:
            game.FinalWrapUp();
            break;
        case Step::FINAL_GAMEOVER:
            game.FinalGameOver();
            break;
        default:
            break;
    }
}
}  // namespace RosettaStone
<|endoftext|>


<commit_before>//
// Name: ResampleDlg.cpp
//
// Copyright (c) 2001-2006 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "ResampleDlg.h"
#include "TileDlg.h"
#include "FileFilters.h"
#include "RenderOptionsDlg.h"
#include "Helper.h"	// for GetDataPaths

// WDR: class implementations

//----------------------------------------------------------------------------
// ResampleDlg
//----------------------------------------------------------------------------

// WDR: event table for ResampleDlg

BEGIN_EVENT_TABLE(ResampleDlg, AutoDialog)
	EVT_INIT_DIALOG (ResampleDlg::OnInitDialog)
	EVT_BUTTON( ID_SMALLER, ResampleDlg::OnSmaller )
	EVT_BUTTON( ID_BIGGER, ResampleDlg::OnBigger )
	EVT_CHECKBOX( ID_CONSTRAIN, ResampleDlg::OnConstrain )
	EVT_TEXT( ID_SIZEX, ResampleDlg::OnSizeXY )
	EVT_TEXT( ID_SIZEY, ResampleDlg::OnSizeXY )
	EVT_TEXT( ID_SPACINGX, ResampleDlg::OnSpacingXY )
	EVT_TEXT( ID_SPACINGY, ResampleDlg::OnSpacingXY )
	EVT_RADIOBUTTON( ID_FLOATS, ResampleDlg::OnFloats )
	EVT_RADIOBUTTON( ID_SHORTS, ResampleDlg::OnShorts )
	EVT_RADIOBUTTON( ID_RADIO_CREATE_NEW, ResampleDlg::OnRadioOutput )
	EVT_RADIOBUTTON( ID_RADIO_TO_FILE, ResampleDlg::OnRadioOutput )
	EVT_RADIOBUTTON( ID_RADIO_TO_TILES, ResampleDlg::OnRadioOutput )
	EVT_BUTTON( ID_DOTDOTDOT, ResampleDlg::OnDotDotDot )
	EVT_BUTTON( ID_TILE_OPTIONS, ResampleDlg::OnTileOptions )
	EVT_CHECKBOX( ID_DERIVED_IMAGES, ResampleDlg::OnCheckDerivedImages )
	EVT_BUTTON( ID_RENDERING_OPTIONS, ResampleDlg::OnRenderingOptions )
	EVT_TEXT( ID_TEXT_TO_IMAGE_FILE, ResampleDlg::OnTextToImageFile )
	EVT_BUTTON( ID_DOTDOTDOT2, ResampleDlg::OnDotDotDot2 )
END_EVENT_TABLE()

ResampleDlg::ResampleDlg( wxWindow *parent, wxWindowID id, const wxString &title,
	const wxPoint &position, const wxSize& size, long style ) :
	AutoDialog( parent, id, title, position, size, style )
{
	ResampleDialogFunc( this, TRUE );
	m_bSetting = false;

	m_bNewLayer = true;
	m_bToFile = false;
	m_bToTiles = false;
	m_bFillGaps = true;

	m_tileopts.cols = 4;
	m_tileopts.rows = 4;
	m_tileopts.lod0size = 256;
	m_tileopts.numlods = 3;
	m_tileopts.bCreateDerivedImages = false;
	m_tileopts.fname_images = "";

	FormatTilingString();

	// output options
	AddValidator(ID_RADIO_CREATE_NEW, &m_bNewLayer);
	AddValidator(ID_RADIO_TO_FILE, &m_bToFile);
	AddValidator(ID_RADIO_TO_TILES, &m_bToTiles);

	AddValidator(ID_TEXT_TO_FILE, &m_strToFile);
	AddValidator(ID_TEXT_TILE_INFO, &m_strTileInfo);

	AddValidator(ID_DERIVED_IMAGES, &m_tileopts.bCreateDerivedImages);
	AddValidator(ID_TEXT_TO_IMAGE_FILE, &m_strToFileImages);

	// sampling
	spacing1 = AddNumValidator(ID_SPACINGX, &m_fSpacingX);
	spacing2 = AddNumValidator(ID_SPACINGY, &m_fSpacingY);
	AddNumValidator(ID_SIZEX, &m_iSizeX);
	AddNumValidator(ID_SIZEY, &m_iSizeY);
	AddValidator(ID_CONSTRAIN, &m_bConstraint);

	// output grid
	AddValidator(ID_FLOATS, &m_bFloats);
	AddNumValidator(ID_VUNITS, &m_fVUnits);
	AddValidator(ID_FILL_GAPS, &m_bFillGaps);

	// informations
	AddNumValidator(ID_AREAX, &m_fAreaX);
	AddNumValidator(ID_AREAY, &m_fAreaY);

	AddNumValidator(ID_ESTX, &m_fEstX);
	AddNumValidator(ID_ESTY, &m_fEstY);
}

void ResampleDlg::OnInitDialog(wxInitDialogEvent& event)
{
	m_bNewLayer = true;
	m_bToFile = false;

	m_power = 8;
	m_bConstraint = false;
	m_fVUnits = 1.0f;

	m_fAreaX = m_area.Width();
	m_fAreaY = m_area.Height();

	// initial value: based on estimate spacing
	m_fSpacingX = m_fEstX;
	m_fSpacingY = m_fEstY;
	m_iSizeX = ((int) (m_fAreaX / m_fSpacingX + 0.5)) + 1;
	m_iSizeY = ((int) (m_fAreaY / m_fSpacingY + 0.5)) + 1;

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;

	EnableBasedOnConstraint();

	GetShorts()->SetValue(!m_bFloats);
}

void ResampleDlg::RecomputeSize()
{
	if (m_bToTiles)
	{
		m_iSizeX = m_tileopts.cols * m_tileopts.lod0size + 1;
		m_iSizeY = m_tileopts.rows * m_tileopts.lod0size + 1;
	}
	else if (m_bConstraint)  // powers of 2 + 1
		m_iSizeX = m_iSizeY = (1 << m_power) + 1;

	m_fSpacingX = m_fAreaX / (m_iSizeX - 1);
	m_fSpacingY = m_fAreaY / (m_iSizeY - 1);
}

void ResampleDlg::FormatTilingString()
{
	m_strTileInfo.Printf(_T("%d x %d @ %d"), m_tileopts.cols,
		m_tileopts.rows, m_tileopts.lod0size);
}

// WDR: handler implementations for ResampleDlg

void ResampleDlg::OnDotDotDot2( wxCommandEvent &event )
{
	wxString filter;
	filter += FSTRING_INI;
	wxFileDialog saveFile(NULL, _T(".Ini file"), _T(""), _T(""), filter, wxFD_SAVE);
	bool bResult = (saveFile.ShowModal() == wxID_OK);
	if (!bResult)
		return;

	// update controls
	m_strToFileImages = saveFile.GetPath();
	TransferDataToWindow();

	m_tileopts.fname_images = m_strToFileImages.mb_str(wxConvUTF8);
	EnableBasedOnConstraint();
}

void ResampleDlg::OnRenderingOptions( wxCommandEvent &event )
{
	RenderOptionsDlg dlg(this, -1, _("Rendering options"));
	dlg.SetOptions(m_tileopts.draw);
	dlg.m_datapaths = GetDataPaths();
	if (dlg.ShowModal() != wxID_OK)
		return;
	m_tileopts.draw = dlg.m_opt;
}

void ResampleDlg::OnCheckDerivedImages( wxCommandEvent &event )
{
	TransferDataFromWindow();
	EnableBasedOnConstraint();
}

void ResampleDlg::OnTileOptions( wxCommandEvent &event )
{
	TileDlg dlg(this, -1, _("Tiling Options"));

	dlg.m_fEstX = m_fEstX;
	dlg.m_fEstY = m_fEstY;
	dlg.SetElevation(true);
	dlg.SetArea(m_area);
	dlg.SetTilingOptions(m_tileopts);
	dlg.SetView(m_pView);

	if (dlg.ShowModal() == wxID_OK)
	{
		dlg.GetTilingOptions(m_tileopts);
		FormatTilingString();
		RecomputeSize();
		TransferDataToWindow();
	}
}

void ResampleDlg::OnDotDotDot( wxCommandEvent &event )
{
	wxString filter;
	filter += FSTRING_BT;
	filter += _T("|");
	filter += FSTRING_BTGZ;

	// ask the user for a filename
	wxFileDialog saveFile(NULL, _("Save Elevation"), _T(""), _T(""), filter, wxFD_SAVE);
	saveFile.SetFilterIndex(0);
	bool bResult = (saveFile.ShowModal() == wxID_OK);
	if (!bResult)
		return;

	wxString name = saveFile.GetPath();

	// work around incorrect extension(s) that wxFileDialog added
	bool bPreferGZip = (saveFile.GetFilterIndex() == 1);

	if (!name.Right(3).CmpNoCase(_T(".gz")))
		name = name.Left(name.Len()-3);
	if (!name.Right(3).CmpNoCase(_T(".bt")))
		name = name.Left(name.Len()-3);

	if (bPreferGZip)
		name += _T(".bt.gz");
	else
		name += _T(".bt");

	m_strToFile = name;

	// update controls
	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::OnRadioOutput( wxCommandEvent &event )
{
	TransferDataFromWindow();
	EnableBasedOnConstraint();
	RecomputeSize();
	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::OnTextToImageFile( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	m_tileopts.fname_images = m_strToFileImages.mb_str(wxConvUTF8);
	EnableBasedOnConstraint();
}

void ResampleDlg::OnShorts( wxCommandEvent &event )
{
	GetVUnits()->Enable(true);
}

void ResampleDlg::OnFloats( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	m_fVUnits = 1.0f;
	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
	EnableBasedOnConstraint();
}

void ResampleDlg::OnSpacingXY( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	m_iSizeX = (int) (m_fAreaX / m_fSpacingX)+1;
	m_iSizeY = (int) (m_fAreaY / m_fSpacingY)+1;

	m_bSetting = true;
	spacing1->Enable(false);
	spacing2->Enable(false);
	TransferDataToWindow();
	spacing1->Enable(true);
	spacing2->Enable(true);
	m_bSetting = false;
}

void ResampleDlg::OnSizeXY( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	RecomputeSize();

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::OnConstrain( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	if (m_bConstraint)
	{
		// round up to a value at least as great as the current size
		m_power = 1;
		while (((1 << m_power) + 1) < m_iSizeX ||
			   ((1 << m_power) + 1) < m_iSizeY)
			m_power++;
	}
	RecomputeSize();
	EnableBasedOnConstraint();

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::EnableBasedOnConstraint()
{
	GetTextToFile()->Enable(m_bToFile);
	GetDotDotDot()->Enable(m_bToFile);

	GetTextTileInfo()->Enable(m_bToTiles);
	GetTileOptions()->Enable(m_bToTiles);
	GetDerivedImages()->Enable(m_bToTiles);

	GetRenderingOptions()->Enable(m_bToTiles && m_tileopts.bCreateDerivedImages);
	GetTextToImageFile()->Enable(m_bToTiles && m_tileopts.bCreateDerivedImages);
	GetDotdotdot2()->Enable(m_bToTiles && m_tileopts.bCreateDerivedImages);

	GetConstrain()->Enable(!m_bToTiles);
	GetSmaller()->Enable(m_bConstraint && !m_bToTiles);
	GetBigger()->Enable(m_bConstraint && !m_bToTiles);

	GetSizeX()->SetEditable(!m_bConstraint && !m_bToTiles);
	GetSizeY()->SetEditable(!m_bConstraint && !m_bToTiles);
	GetSpacingX()->SetEditable(!m_bConstraint && !m_bToTiles);
	GetSpacingY()->SetEditable(!m_bConstraint && !m_bToTiles);

	GetVUnits()->Enable(!m_bFloats);

	// If they've selected derived images, they must have an output file
	//  in order to proceed
	FindWindow(wxID_OK)->Enable(!m_tileopts.bCreateDerivedImages ||
		m_tileopts.fname_images != "");
}

void ResampleDlg::OnBigger( wxCommandEvent &event )
{
	m_power++;
	RecomputeSize();

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::OnSmaller( wxCommandEvent &event )
{
	m_power--;
	RecomputeSize();

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

<commit_msg>fixed problem with OK button being disabled incorrectly<commit_after>//
// Name: ResampleDlg.cpp
//
// Copyright (c) 2001-2007 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

#include "ResampleDlg.h"
#include "TileDlg.h"
#include "FileFilters.h"
#include "RenderOptionsDlg.h"
#include "Helper.h"	// for GetDataPaths

// WDR: class implementations

//----------------------------------------------------------------------------
// ResampleDlg
//----------------------------------------------------------------------------

// WDR: event table for ResampleDlg

BEGIN_EVENT_TABLE(ResampleDlg, AutoDialog)
	EVT_INIT_DIALOG (ResampleDlg::OnInitDialog)
	EVT_BUTTON( ID_SMALLER, ResampleDlg::OnSmaller )
	EVT_BUTTON( ID_BIGGER, ResampleDlg::OnBigger )
	EVT_CHECKBOX( ID_CONSTRAIN, ResampleDlg::OnConstrain )
	EVT_TEXT( ID_SIZEX, ResampleDlg::OnSizeXY )
	EVT_TEXT( ID_SIZEY, ResampleDlg::OnSizeXY )
	EVT_TEXT( ID_SPACINGX, ResampleDlg::OnSpacingXY )
	EVT_TEXT( ID_SPACINGY, ResampleDlg::OnSpacingXY )
	EVT_RADIOBUTTON( ID_FLOATS, ResampleDlg::OnFloats )
	EVT_RADIOBUTTON( ID_SHORTS, ResampleDlg::OnShorts )
	EVT_RADIOBUTTON( ID_RADIO_CREATE_NEW, ResampleDlg::OnRadioOutput )
	EVT_RADIOBUTTON( ID_RADIO_TO_FILE, ResampleDlg::OnRadioOutput )
	EVT_RADIOBUTTON( ID_RADIO_TO_TILES, ResampleDlg::OnRadioOutput )
	EVT_BUTTON( ID_DOTDOTDOT, ResampleDlg::OnDotDotDot )
	EVT_BUTTON( ID_TILE_OPTIONS, ResampleDlg::OnTileOptions )
	EVT_CHECKBOX( ID_DERIVED_IMAGES, ResampleDlg::OnCheckDerivedImages )
	EVT_BUTTON( ID_RENDERING_OPTIONS, ResampleDlg::OnRenderingOptions )
	EVT_TEXT( ID_TEXT_TO_IMAGE_FILE, ResampleDlg::OnTextToImageFile )
	EVT_BUTTON( ID_DOTDOTDOT2, ResampleDlg::OnDotDotDot2 )
END_EVENT_TABLE()

ResampleDlg::ResampleDlg( wxWindow *parent, wxWindowID id, const wxString &title,
	const wxPoint &position, const wxSize& size, long style ) :
	AutoDialog( parent, id, title, position, size, style )
{
	ResampleDialogFunc( this, TRUE );
	m_bSetting = false;

	m_bNewLayer = true;
	m_bToFile = false;
	m_bToTiles = false;
	m_bFillGaps = true;

	m_tileopts.cols = 4;
	m_tileopts.rows = 4;
	m_tileopts.lod0size = 256;
	m_tileopts.numlods = 3;
	m_tileopts.bCreateDerivedImages = false;
	m_tileopts.fname_images = "";

	FormatTilingString();

	// output options
	AddValidator(ID_RADIO_CREATE_NEW, &m_bNewLayer);
	AddValidator(ID_RADIO_TO_FILE, &m_bToFile);
	AddValidator(ID_RADIO_TO_TILES, &m_bToTiles);

	AddValidator(ID_TEXT_TO_FILE, &m_strToFile);
	AddValidator(ID_TEXT_TILE_INFO, &m_strTileInfo);

	AddValidator(ID_DERIVED_IMAGES, &m_tileopts.bCreateDerivedImages);
	AddValidator(ID_TEXT_TO_IMAGE_FILE, &m_strToFileImages);

	// sampling
	spacing1 = AddNumValidator(ID_SPACINGX, &m_fSpacingX);
	spacing2 = AddNumValidator(ID_SPACINGY, &m_fSpacingY);
	AddNumValidator(ID_SIZEX, &m_iSizeX);
	AddNumValidator(ID_SIZEY, &m_iSizeY);
	AddValidator(ID_CONSTRAIN, &m_bConstraint);

	// output grid
	AddValidator(ID_FLOATS, &m_bFloats);
	AddNumValidator(ID_VUNITS, &m_fVUnits);
	AddValidator(ID_FILL_GAPS, &m_bFillGaps);

	// informations
	AddNumValidator(ID_AREAX, &m_fAreaX);
	AddNumValidator(ID_AREAY, &m_fAreaY);

	AddNumValidator(ID_ESTX, &m_fEstX);
	AddNumValidator(ID_ESTY, &m_fEstY);
}

void ResampleDlg::OnInitDialog(wxInitDialogEvent& event)
{
	m_bNewLayer = true;
	m_bToFile = false;

	m_power = 8;
	m_bConstraint = false;
	m_fVUnits = 1.0f;

	m_fAreaX = m_area.Width();
	m_fAreaY = m_area.Height();

	// initial value: based on estimate spacing
	m_fSpacingX = m_fEstX;
	m_fSpacingY = m_fEstY;
	m_iSizeX = ((int) (m_fAreaX / m_fSpacingX + 0.5)) + 1;
	m_iSizeY = ((int) (m_fAreaY / m_fSpacingY + 0.5)) + 1;

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;

	EnableBasedOnConstraint();

	GetShorts()->SetValue(!m_bFloats);
}

void ResampleDlg::RecomputeSize()
{
	if (m_bToTiles)
	{
		m_iSizeX = m_tileopts.cols * m_tileopts.lod0size + 1;
		m_iSizeY = m_tileopts.rows * m_tileopts.lod0size + 1;
	}
	else if (m_bConstraint)  // powers of 2 + 1
		m_iSizeX = m_iSizeY = (1 << m_power) + 1;

	m_fSpacingX = m_fAreaX / (m_iSizeX - 1);
	m_fSpacingY = m_fAreaY / (m_iSizeY - 1);
}

void ResampleDlg::FormatTilingString()
{
	m_strTileInfo.Printf(_T("%d x %d @ %d"), m_tileopts.cols,
		m_tileopts.rows, m_tileopts.lod0size);
}

// WDR: handler implementations for ResampleDlg

void ResampleDlg::OnDotDotDot2( wxCommandEvent &event )
{
	wxString filter;
	filter += FSTRING_INI;
	wxFileDialog saveFile(NULL, _T(".Ini file"), _T(""), _T(""), filter, wxFD_SAVE);
	bool bResult = (saveFile.ShowModal() == wxID_OK);
	if (!bResult)
		return;

	// update controls
	m_strToFileImages = saveFile.GetPath();
	TransferDataToWindow();

	m_tileopts.fname_images = m_strToFileImages.mb_str(wxConvUTF8);
	EnableBasedOnConstraint();
}

void ResampleDlg::OnRenderingOptions( wxCommandEvent &event )
{
	RenderOptionsDlg dlg(this, -1, _("Rendering options"));
	dlg.SetOptions(m_tileopts.draw);
	dlg.m_datapaths = GetDataPaths();
	if (dlg.ShowModal() != wxID_OK)
		return;
	m_tileopts.draw = dlg.m_opt;
}

void ResampleDlg::OnCheckDerivedImages( wxCommandEvent &event )
{
	TransferDataFromWindow();
	EnableBasedOnConstraint();
}

void ResampleDlg::OnTileOptions( wxCommandEvent &event )
{
	TileDlg dlg(this, -1, _("Tiling Options"));

	dlg.m_fEstX = m_fEstX;
	dlg.m_fEstY = m_fEstY;
	dlg.SetElevation(true);
	dlg.SetArea(m_area);
	dlg.SetTilingOptions(m_tileopts);
	dlg.SetView(m_pView);

	if (dlg.ShowModal() == wxID_OK)
	{
		dlg.GetTilingOptions(m_tileopts);
		FormatTilingString();
		RecomputeSize();
		TransferDataToWindow();
	}
}

void ResampleDlg::OnDotDotDot( wxCommandEvent &event )
{
	wxString filter;
	filter += FSTRING_BT;
	filter += _T("|");
	filter += FSTRING_BTGZ;

	// ask the user for a filename
	wxFileDialog saveFile(NULL, _("Save Elevation"), _T(""), _T(""), filter, wxFD_SAVE);
	saveFile.SetFilterIndex(0);
	bool bResult = (saveFile.ShowModal() == wxID_OK);
	if (!bResult)
		return;

	wxString name = saveFile.GetPath();

	// work around incorrect extension(s) that wxFileDialog added
	bool bPreferGZip = (saveFile.GetFilterIndex() == 1);

	if (!name.Right(3).CmpNoCase(_T(".gz")))
		name = name.Left(name.Len()-3);
	if (!name.Right(3).CmpNoCase(_T(".bt")))
		name = name.Left(name.Len()-3);

	if (bPreferGZip)
		name += _T(".bt.gz");
	else
		name += _T(".bt");

	m_strToFile = name;

	// update controls
	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::OnRadioOutput( wxCommandEvent &event )
{
	TransferDataFromWindow();
	EnableBasedOnConstraint();
	RecomputeSize();
	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::OnTextToImageFile( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	m_tileopts.fname_images = m_strToFileImages.mb_str(wxConvUTF8);
	EnableBasedOnConstraint();
}

void ResampleDlg::OnShorts( wxCommandEvent &event )
{
	GetVUnits()->Enable(true);
}

void ResampleDlg::OnFloats( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	m_fVUnits = 1.0f;
	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
	EnableBasedOnConstraint();
}

void ResampleDlg::OnSpacingXY( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	m_iSizeX = (int) (m_fAreaX / m_fSpacingX)+1;
	m_iSizeY = (int) (m_fAreaY / m_fSpacingY)+1;

	m_bSetting = true;
	spacing1->Enable(false);
	spacing2->Enable(false);
	TransferDataToWindow();
	spacing1->Enable(true);
	spacing2->Enable(true);
	m_bSetting = false;
}

void ResampleDlg::OnSizeXY( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	RecomputeSize();

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::OnConstrain( wxCommandEvent &event )
{
	if (m_bSetting)
		return;

	TransferDataFromWindow();
	if (m_bConstraint)
	{
		// round up to a value at least as great as the current size
		m_power = 1;
		while (((1 << m_power) + 1) < m_iSizeX ||
			   ((1 << m_power) + 1) < m_iSizeY)
			m_power++;
	}
	RecomputeSize();
	EnableBasedOnConstraint();

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::EnableBasedOnConstraint()
{
	GetTextToFile()->Enable(m_bToFile);
	GetDotDotDot()->Enable(m_bToFile);

	GetTextTileInfo()->Enable(m_bToTiles);
	GetTileOptions()->Enable(m_bToTiles);
	GetDerivedImages()->Enable(m_bToTiles);

	GetRenderingOptions()->Enable(m_bToTiles && m_tileopts.bCreateDerivedImages);
	GetTextToImageFile()->Enable(m_bToTiles && m_tileopts.bCreateDerivedImages);
	GetDotdotdot2()->Enable(m_bToTiles && m_tileopts.bCreateDerivedImages);

	GetConstrain()->Enable(!m_bToTiles);
	GetSmaller()->Enable(m_bConstraint && !m_bToTiles);
	GetBigger()->Enable(m_bConstraint && !m_bToTiles);

	GetSizeX()->SetEditable(!m_bConstraint && !m_bToTiles);
	GetSizeY()->SetEditable(!m_bConstraint && !m_bToTiles);
	GetSpacingX()->SetEditable(!m_bConstraint && !m_bToTiles);
	GetSpacingY()->SetEditable(!m_bConstraint && !m_bToTiles);

	GetVUnits()->Enable(!m_bFloats);

	// If they've selected derived images, they must have an output file
	//  in order to proceed
	bool bOk = true;
	if (m_bToTiles)
	{
		if (m_tileopts.bCreateDerivedImages && m_tileopts.fname_images == "")
			bOk = false;
	}
	FindWindow(wxID_OK)->Enable(bOk);
}

void ResampleDlg::OnBigger( wxCommandEvent &event )
{
	m_power++;
	RecomputeSize();

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

void ResampleDlg::OnSmaller( wxCommandEvent &event )
{
	m_power--;
	RecomputeSize();

	m_bSetting = true;
	TransferDataToWindow();
	m_bSetting = false;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: share.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2003-04-28 16:29:01 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/

#include <typeinfo>
#include <exception>
#include <cstddef>

namespace CPPU_CURRENT_NAMESPACE
{

// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h

struct _Unwind_Exception
{
    unsigned exception_class __attribute__((__mode__(__DI__)));
    void * exception_cleanup;
    unsigned private_1 __attribute__((__mode__(__word__)));
    unsigned private_2 __attribute__((__mode__(__word__)));
} __attribute__((__aligned__));

struct __cxa_exception
{
    ::std::type_info *exceptionType;
    void (*exceptionDestructor)(void *);

    ::std::unexpected_handler unexpectedHandler;
    ::std::terminate_handler terminateHandler;

    __cxa_exception *nextException;

    int handlerCount;

    int handlerSwitchValue;
    const unsigned char *actionRecord;
    const unsigned char *languageSpecificData;
    void *catchTemp;
    void *adjustedPtr;

    _Unwind_Exception unwindHeader;
};

extern "C" void *__cxa_allocate_exception(
    std::size_t thrown_size ) throw();
extern "C" void __cxa_throw (
    void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn));

struct __cxa_eh_globals
{
    __cxa_exception *caughtExceptions;
    unsigned int uncaughtExceptions;
};
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();

//==================================================================================================
void raiseException(
    uno_Any * pUnoExc, uno_Mapping * pUno2Cpp );
//==================================================================================================
void fillUnoException(
    __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno );

inline char* adjustPointer( char* pIn, typelib_TypeDescription* pType )
{
    switch( pType->nSize )
    {
        case 1: return pIn + 3;
        case 2: return pIn + 2;
        case 3: return pIn + 1;
            // Huh ? perhaps a char[3] ? Though that would be a pointer
            // well, we have it anyway for symmetry
    }
    return pIn;
}

}
<commit_msg>INTEGRATION: CWS ooo20040329 (1.2.90); FILE MERGED 2004/03/18 11:25:54 sparcmoz 1.2.90.1: #i24507# linux sparc new code for multi-inherit bridges<commit_after>/*************************************************************************
 *
 *  $RCSfile: share.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: svesik $ $Date: 2004-04-21 13:41:36 $
 *
 *  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): _______________________________________
 *
 *
 ************************************************************************/
#include "uno/mapping.h"
#include <typeinfo>
#include <exception>
#include <cstddef>
namespace CPPU_CURRENT_NAMESPACE
{
void dummy_can_throw_anything( char const * );
// ----- following decl from libstdc++-v3/libsupc++/unwind-cxx.h and unwind.h

struct _Unwind_Exception
{
    unsigned exception_class __attribute__((__mode__(__DI__)));
    void * exception_cleanup;
    unsigned private_1 __attribute__((__mode__(__word__)));
    unsigned private_2 __attribute__((__mode__(__word__)));
} __attribute__((__aligned__));

struct __cxa_exception
{
    ::std::type_info *exceptionType;
    void (*exceptionDestructor)(void *);

    ::std::unexpected_handler unexpectedHandler;
    ::std::terminate_handler terminateHandler;

    __cxa_exception *nextException;

    int handlerCount;

    int handlerSwitchValue;
    const unsigned char *actionRecord;
    const unsigned char *languageSpecificData;
    void *catchTemp;
    void *adjustedPtr;

    _Unwind_Exception unwindHeader;
};

extern "C" void *__cxa_allocate_exception(
    std::size_t thrown_size ) throw();
extern "C" void __cxa_throw (
    void *thrown_exception, std::type_info *tinfo, void (*dest) (void *) ) __attribute__((noreturn));

struct __cxa_eh_globals
{
    __cxa_exception *caughtExceptions;
    unsigned int uncaughtExceptions;
};
extern "C" __cxa_eh_globals *__cxa_get_globals () throw();

//==================================================================================================
void raiseException(
    uno_Any * pUnoExc, uno_Mapping * pUno2Cpp );
//==================================================================================================
void fillUnoException(
    __cxa_exception * header, uno_Any *, uno_Mapping * pCpp2Uno );

inline char* adjustPointer( char* pIn, typelib_TypeDescription* pType )
{
    switch( pType->nSize )
    {
        case 1: return pIn + 3;
        case 2: return pIn + 2;
        case 3: return pIn + 1;
            // Huh ? perhaps a char[3] ? Though that would be a pointer
            // well, we have it anyway for symmetry
    }
    return pIn;
}

}
<|endoftext|>