<commit_before>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/Attributes>

#include <osgUtil/SceneView.orig>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

TYPE_NAME_ALIAS(osgUtil::SceneView::Options, osgUtil::SceneView::LightingMode);

BEGIN_ENUM_REFLECTOR(osgUtil::SceneView::Options)
	I_EnumLabel(osgUtil::SceneView::NO_SCENEVIEW_LIGHT);
	I_EnumLabel(osgUtil::SceneView::HEADLIGHT);
	I_EnumLabel(osgUtil::SceneView::SKY_LIGHT);
	I_EnumLabel(osgUtil::SceneView::COMPILE_GLOBJECTS_AT_INIT);
	I_EnumLabel(osgUtil::SceneView::STANDARD_SETTINGS);
END_REFLECTOR

BEGIN_ENUM_REFLECTOR(osgUtil::SceneView::ActiveUniforms)
	I_EnumLabel(osgUtil::SceneView::FRAME_NUMBER_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::FRAME_TIME_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::DELTA_FRAME_TIME_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::VIEW_MATRIX_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::VIEW_MATRIX_INVERSE_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::DEFAULT_UNIFORMS);
	I_EnumLabel(osgUtil::SceneView::ALL_UNIFORMS);
END_REFLECTOR

BEGIN_ENUM_REFLECTOR(osgUtil::SceneView::FusionDistanceMode)
	I_EnumLabel(osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE);
	I_EnumLabel(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE);
END_REFLECTOR

<commit_msg>Updated wrappers.<commit_after>// ***************************************************************************
//
//   Generated automatically by genwrapper.
//   Please DO NOT EDIT this file!
//
// ***************************************************************************

#include <osgIntrospection/ReflectionMacros>
#include <osgIntrospection/TypedMethodInfo>
#include <osgIntrospection/Attributes>

#include <osg/CameraNode>
#include <osg/CollectOccludersVisitor>
#include <osg/DisplaySettings>
#include <osg/FrameStamp>
#include <osg/Light>
#include <osg/Matrixd>
#include <osg/Matrixf>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osg/State>
#include <osg/StateSet>
#include <osg/Vec3>
#include <osg/Vec4>
#include <osg/Viewport>
#include <osgUtil/CullVisitor>
#include <osgUtil/RenderStage>
#include <osgUtil/SceneView>
#include <osgUtil/StateGraph>

// Must undefine IN and OUT macros defined in Windows headers
#ifdef IN
#undef IN
#endif
#ifdef OUT
#undef OUT
#endif

TYPE_NAME_ALIAS(osgUtil::SceneView::Options, osgUtil::SceneView::LightingMode);

BEGIN_ENUM_REFLECTOR(osgUtil::SceneView::Options)
	I_EnumLabel(osgUtil::SceneView::NO_SCENEVIEW_LIGHT);
	I_EnumLabel(osgUtil::SceneView::HEADLIGHT);
	I_EnumLabel(osgUtil::SceneView::SKY_LIGHT);
	I_EnumLabel(osgUtil::SceneView::COMPILE_GLOBJECTS_AT_INIT);
	I_EnumLabel(osgUtil::SceneView::STANDARD_SETTINGS);
END_REFLECTOR

BEGIN_ENUM_REFLECTOR(osgUtil::SceneView::ActiveUniforms)
	I_EnumLabel(osgUtil::SceneView::FRAME_NUMBER_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::FRAME_TIME_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::DELTA_FRAME_TIME_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::VIEW_MATRIX_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::VIEW_MATRIX_INVERSE_UNIFORM);
	I_EnumLabel(osgUtil::SceneView::DEFAULT_UNIFORMS);
	I_EnumLabel(osgUtil::SceneView::ALL_UNIFORMS);
END_REFLECTOR

BEGIN_ENUM_REFLECTOR(osgUtil::SceneView::FusionDistanceMode)
	I_EnumLabel(osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE);
	I_EnumLabel(osgUtil::SceneView::PROPORTIONAL_TO_SCREEN_DISTANCE);
END_REFLECTOR

BEGIN_OBJECT_REFLECTOR(osgUtil::SceneView)
	I_BaseType(osg::Referenced);
	I_BaseType(osg::CullSettings);
	I_ConstructorWithDefaults1(IN, osg::DisplaySettings *, ds, NULL);
	I_MethodWithDefaults1(void, setDefaults, IN, unsigned int, options, osgUtil::SceneView::STANDARD_SETTINGS);
	I_Method1(void, setCamera, IN, osg::CameraNode *, camera);
	I_Method0(osg::CameraNode *, getCamera);
	I_Method0(const osg::CameraNode *, getCamera);
	I_Method1(void, setSceneData, IN, osg::Node *, node);
	I_MethodWithDefaults1(osg::Node *, getSceneData, IN, unsigned int, childNo, 0);
	I_MethodWithDefaults1(const osg::Node *, getSceneData, IN, unsigned int, childNo, 0);
	I_Method0(unsigned int, getNumSceneData);
	I_Method1(void, setViewport, IN, osg::Viewport *, viewport);
	I_Method4(void, setViewport, IN, int, x, IN, int, y, IN, int, width, IN, int, height);
	I_Method0(osg::Viewport *, getViewport);
	I_Method0(const osg::Viewport *, getViewport);
	I_Method4(void, getViewport, IN, int &, x, IN, int &, y, IN, int &, width, IN, int &, height);
	I_Method1(void, setDisplaySettings, IN, osg::DisplaySettings *, vs);
	I_Method0(const osg::DisplaySettings *, getDisplaySettings);
	I_Method0(osg::DisplaySettings *, getDisplaySettings);
	I_Method1(void, setClearColor, IN, const osg::Vec4 &, color);
	I_Method0(const osg::Vec4 &, getClearColor);
	I_Method1(void, setRedrawInterlacedStereoStencilMask, IN, bool, flag);
	I_Method0(bool, getRedrawInterlacedStereoStencilMask);
	I_Method1(void, setGlobalStateSet, IN, osg::StateSet *, state);
	I_Method0(osg::StateSet *, getGlobalStateSet);
	I_Method0(const osg::StateSet *, getGlobalStateSet);
	I_Method1(void, setLocalStateSet, IN, osg::StateSet *, state);
	I_Method0(osg::StateSet *, getLocalStateSet);
	I_Method0(const osg::StateSet *, getLocalStateSet);
	I_Method1(void, setActiveUniforms, IN, int, activeUniforms);
	I_Method0(int, getActiveUniforms);
	I_Method0(void, updateUniforms);
	I_Method1(void, setLightingMode, IN, osgUtil::SceneView::LightingMode, mode);
	I_Method0(osgUtil::SceneView::LightingMode, getLightingMode);
	I_Method1(void, setLight, IN, osg::Light *, light);
	I_Method0(osg::Light *, getLight);
	I_Method0(const osg::Light *, getLight);
	I_Method1(void, setState, IN, osg::State *, state);
	I_Method0(osg::State *, getState);
	I_Method0(const osg::State *, getState);
	I_Method1(void, setProjectionMatrix, IN, const osg::Matrixf &, matrix);
	I_Method1(void, setProjectionMatrix, IN, const osg::Matrixd &, matrix);
	I_Method6(void, setProjectionMatrixAsOrtho, IN, double, left, IN, double, right, IN, double, bottom, IN, double, top, IN, double, zNear, IN, double, zFar);
	I_Method4(void, setProjectionMatrixAsOrtho2D, IN, double, left, IN, double, right, IN, double, bottom, IN, double, top);
	I_Method6(void, setProjectionMatrixAsFrustum, IN, double, left, IN, double, right, IN, double, bottom, IN, double, top, IN, double, zNear, IN, double, zFar);
	I_Method4(void, setProjectionMatrixAsPerspective, IN, double, fovy, IN, double, aspectRatio, IN, double, zNear, IN, double, zFar);
	I_Method0(osg::Matrixd &, getProjectionMatrix);
	I_Method0(const osg::Matrixd &, getProjectionMatrix);
	I_Method6(bool, getProjectionMatrixAsOrtho, IN, double &, left, IN, double &, right, IN, double &, bottom, IN, double &, top, IN, double &, zNear, IN, double &, zFar);
	I_Method6(bool, getProjectionMatrixAsFrustum, IN, double &, left, IN, double &, right, IN, double &, bottom, IN, double &, top, IN, double &, zNear, IN, double &, zFar);
	I_Method4(bool, getProjectionMatrixAsPerspective, IN, double &, fovy, IN, double &, aspectRatio, IN, double &, zNear, IN, double &, zFar);
	I_Method1(void, setViewMatrix, IN, const osg::Matrixf &, matrix);
	I_Method1(void, setViewMatrix, IN, const osg::Matrixd &, matrix);
	I_Method3(void, setViewMatrixAsLookAt, IN, const osg::Vec3 &, eye, IN, const osg::Vec3 &, center, IN, const osg::Vec3 &, up);
	I_Method0(osg::Matrixd &, getViewMatrix);
	I_Method0(const osg::Matrixd &, getViewMatrix);
	I_MethodWithDefaults4(void, getViewMatrixAsLookAt, IN, osg::Vec3 &, eye, , IN, osg::Vec3 &, center, , IN, osg::Vec3 &, up, , IN, float, lookDistance, 1.0f);
	I_Method1(void, setInitVisitor, IN, osg::NodeVisitor *, av);
	I_Method0(osg::NodeVisitor *, getInitVisitor);
	I_Method0(const osg::NodeVisitor *, getInitVisitor);
	I_Method1(void, setUpdateVisitor, IN, osg::NodeVisitor *, av);
	I_Method0(osg::NodeVisitor *, getUpdateVisitor);
	I_Method0(const osg::NodeVisitor *, getUpdateVisitor);
	I_Method1(void, setCullVisitor, IN, osgUtil::CullVisitor *, cv);
	I_Method0(osgUtil::CullVisitor *, getCullVisitor);
	I_Method0(const osgUtil::CullVisitor *, getCullVisitor);
	I_Method1(void, setCullVisitorLeft, IN, osgUtil::CullVisitor *, cv);
	I_Method0(osgUtil::CullVisitor *, getCullVisitorLeft);
	I_Method0(const osgUtil::CullVisitor *, getCullVisitorLeft);
	I_Method1(void, setCullVisitorRight, IN, osgUtil::CullVisitor *, cv);
	I_Method0(osgUtil::CullVisitor *, getCullVisitorRight);
	I_Method0(const osgUtil::CullVisitor *, getCullVisitorRight);
	I_Method1(void, setCollectOccludersVisitor, IN, osg::CollectOccludersVisitor *, cov);
	I_Method0(osg::CollectOccludersVisitor *, getCollectOccludersVisitor);
	I_Method0(const osg::CollectOccludersVisitor *, getCollectOccludersVisitor);
	I_Method1(void, setStateGraph, IN, osgUtil::StateGraph *, rg);
	I_Method0(osgUtil::StateGraph *, getStateGraph);
	I_Method0(const osgUtil::StateGraph *, getStateGraph);
	I_Method1(void, setStateGraphLeft, IN, osgUtil::StateGraph *, rg);
	I_Method0(osgUtil::StateGraph *, getStateGraphLeft);
	I_Method0(const osgUtil::StateGraph *, getStateGraphLeft);
	I_Method1(void, setStateGraphRight, IN, osgUtil::StateGraph *, rg);
	I_Method0(osgUtil::StateGraph *, getStateGraphRight);
	I_Method0(const osgUtil::StateGraph *, getStateGraphRight);
	I_Method1(void, setRenderStage, IN, osgUtil::RenderStage *, rs);
	I_Method0(osgUtil::RenderStage *, getRenderStage);
	I_Method0(const osgUtil::RenderStage *, getRenderStage);
	I_Method1(void, setRenderStageLeft, IN, osgUtil::RenderStage *, rs);
	I_Method0(osgUtil::RenderStage *, getRenderStageLeft);
	I_Method0(const osgUtil::RenderStage *, getRenderStageLeft);
	I_Method1(void, setRenderStageRight, IN, osgUtil::RenderStage *, rs);
	I_Method0(osgUtil::RenderStage *, getRenderStageRight);
	I_Method0(const osgUtil::RenderStage *, getRenderStageRight);
	I_Method1(void, setDrawBufferValue, IN, GLenum, drawBufferValue);
	I_Method0(GLenum, getDrawBufferValue);
	I_MethodWithDefaults2(void, setFusionDistance, IN, osgUtil::SceneView::FusionDistanceMode, mode, , IN, float, value, 1.0f);
	I_Method0(osgUtil::SceneView::FusionDistanceMode, getFusionDistanceMode);
	I_Method0(float, getFusionDistanceValue);
	I_Method1(void, setPrioritizeTextures, IN, bool, pt);
	I_Method0(bool, getPrioritizeTextures);
	I_Method1(void, setComputeStereoMatricesCallback, IN, osgUtil::SceneView::ComputeStereoMatricesCallback *, callback);
	I_Method0(osgUtil::SceneView::ComputeStereoMatricesCallback *, getComputeStereoMatricesCallback);
	I_Method0(const osgUtil::SceneView::ComputeStereoMatricesCallback *, getComputeStereoMatricesCallback);
	I_Method2(bool, projectWindowIntoObject, IN, const osg::Vec3 &, window, IN, osg::Vec3 &, object);
	I_Method4(bool, projectWindowXYIntoObject, IN, int, x, IN, int, y, IN, osg::Vec3 &, near_point, IN, osg::Vec3 &, far_point);
	I_Method2(bool, projectObjectIntoWindow, IN, const osg::Vec3 &, object, IN, osg::Vec3 &, window);
	I_Method1(void, setFrameStamp, IN, osg::FrameStamp *, fs);
	I_Method0(const osg::FrameStamp *, getFrameStamp);
	I_Method1(osg::Matrixd, computeLeftEyeProjection, IN, const osg::Matrixd &, projection);
	I_Method1(osg::Matrixd, computeLeftEyeView, IN, const osg::Matrixd &, view);
	I_Method1(osg::Matrixd, computeRightEyeProjection, IN, const osg::Matrixd &, projection);
	I_Method1(osg::Matrixd, computeRightEyeView, IN, const osg::Matrixd &, view);
	I_Method1(osg::Matrixd, computeLeftEyeProjectionImplementation, IN, const osg::Matrixd &, projection);
	I_Method1(osg::Matrixd, computeLeftEyeViewImplementation, IN, const osg::Matrixd &, view);
	I_Method1(osg::Matrixd, computeRightEyeProjectionImplementation, IN, const osg::Matrixd &, projection);
	I_Method1(osg::Matrixd, computeRightEyeViewImplementation, IN, const osg::Matrixd &, view);
	I_Method0(void, init);
	I_Method0(void, update);
	I_Method0(void, cull);
	I_Method0(void, draw);
	I_Method0(void, releaseAllGLObjects);
	I_Method0(void, flushAllDeletedGLObjects);
	I_Method1(void, flushDeletedGLObjects, IN, double &, availableTime);
	I_Property(int, ActiveUniforms);
	I_Property(osg::CameraNode *, Camera);
	I_Property(const osg::Vec4 &, ClearColor);
	I_Property(osg::CollectOccludersVisitor *, CollectOccludersVisitor);
	I_Property(osgUtil::SceneView::ComputeStereoMatricesCallback *, ComputeStereoMatricesCallback);
	I_Property(osgUtil::CullVisitor *, CullVisitor);
	I_Property(osgUtil::CullVisitor *, CullVisitorLeft);
	I_Property(osgUtil::CullVisitor *, CullVisitorRight);
	I_WriteOnlyProperty(unsigned int, Defaults);
	I_Property(osg::DisplaySettings *, DisplaySettings);
	I_Property(GLenum, DrawBufferValue);
	I_WriteOnlyProperty(osg::FrameStamp *, FrameStamp);
	I_ReadOnlyProperty(osgUtil::SceneView::FusionDistanceMode, FusionDistanceMode);
	I_ReadOnlyProperty(float, FusionDistanceValue);
	I_Property(osg::StateSet *, GlobalStateSet);
	I_Property(osg::NodeVisitor *, InitVisitor);
	I_Property(osg::Light *, Light);
	I_Property(osgUtil::SceneView::LightingMode, LightingMode);
	I_Property(osg::StateSet *, LocalStateSet);
	I_Property(bool, PrioritizeTextures);
	I_Property(const osg::Matrixd &, ProjectionMatrix);
	I_Property(bool, RedrawInterlacedStereoStencilMask);
	I_Property(osgUtil::RenderStage *, RenderStage);
	I_Property(osgUtil::RenderStage *, RenderStageLeft);
	I_Property(osgUtil::RenderStage *, RenderStageRight);
	I_ArrayProperty_G(const osg::Node *, SceneData, SceneData, unsigned int, void);
	I_Property(osg::State *, State);
	I_Property(osgUtil::StateGraph *, StateGraph);
	I_Property(osgUtil::StateGraph *, StateGraphLeft);
	I_Property(osgUtil::StateGraph *, StateGraphRight);
	I_Property(osg::NodeVisitor *, UpdateVisitor);
	I_Property(const osg::Matrixd &, ViewMatrix);
	I_Property(osg::Viewport *, Viewport);
END_REFLECTOR

BEGIN_ABSTRACT_OBJECT_REFLECTOR(osgUtil::SceneView::ComputeStereoMatricesCallback)
	I_BaseType(osg::Referenced);
	I_Constructor0();
	I_Method1(osg::Matrixd, computeLeftEyeProjection, IN, const osg::Matrixd &, projection);
	I_Method1(osg::Matrixd, computeLeftEyeView, IN, const osg::Matrixd &, view);
	I_Method1(osg::Matrixd, computeRightEyeProjection, IN, const osg::Matrixd &, projection);
	I_Method1(osg::Matrixd, computeRightEyeView, IN, const osg::Matrixd &, view);
END_REFLECTOR

<|endoftext|>


<commit_before>/*
**==============================================================================
**
** Copyright (c) 2003, 2004, 2005, 2006, Michael Brasher, Karl Schopmeyer
** Copyright (c) 2008, Michael E. Brasher
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and associated documentation files (the "Software"),
** to deal in the Software without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Software, and to permit persons to whom the
** Software is furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE.
**
**==============================================================================
*/

#include "MOF_Element.h"

MOF_Element::~MOF_Element()
{

}

void MOF_Element::append(MOF_Element* element)
{
    MOF_ASSERT(this != 0);
    MOF_ASSERT(element != 0);

    for (MOF_Element* p = this; p; p = p->next)
    {
        if (!p->next)
        {
            p->next = element;
            element->next = 0;
            break;
        }
    }
}

size_t MOF_Element::list_size() const
{
    size_t size = 0;

    for (const MOF_Element* p = this; p; p = p->next)
        size++;

    return size;
}

MOF_Element* MOF_Element::clone() const
{
    MOF_ASSERT("not implemented" == 0);
    return 0;
}

MOF_Element* MOF_Element::clone_list() const
{
    MOF_Element* list = 0;

    for (const MOF_Element* p = this; p; p = p->next)
    {
        if (list == 0)
            list = clone();
        else
            list->append(clone());
    }

    return list;
}

void MOF_Element::delete_list()
{
    for (MOF_Element* p = this; p; )
    {
        MOF_Element* next = p->next;
        delete p;
        p = next;
    }
}
<commit_msg>Fix crash when deleting empty list<commit_after>/*
**==============================================================================
**
** Copyright (c) 2003, 2004, 2005, 2006, Michael Brasher, Karl Schopmeyer
** Copyright (c) 2008, Michael E. Brasher
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and associated documentation files (the "Software"),
** to deal in the Software without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Software, and to permit persons to whom the
** Software is furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
** SOFTWARE.
**
**==============================================================================
*/

#include "MOF_Element.h"

MOF_Element::~MOF_Element()
{

}

void MOF_Element::append(MOF_Element* element)
{
    MOF_ASSERT(this != 0);
    MOF_ASSERT(element != 0);

    for (MOF_Element* p = this; p; p = p->next)
    {
        if (!p->next)
        {
            p->next = element;
            element->next = 0;
            break;
        }
    }
}

size_t MOF_Element::list_size() const
{
    size_t size = 0;

    for (const MOF_Element* p = this; p; p = p->next)
        size++;

    return size;
}

MOF_Element* MOF_Element::clone() const
{
    MOF_ASSERT("not implemented" == 0);
    return 0;
}

MOF_Element* MOF_Element::clone_list() const
{
    MOF_Element* list = 0;

    for (const MOF_Element* p = this; p; p = p->next)
    {
        if (list == 0)
            list = clone();
        else
            list->append(clone());
    }

    return list;
}

void MOF_Element::delete_list()
{
    if (this == NULL)
    {
        return;
    }
    for (MOF_Element* p = this; p; )
    {
        MOF_Element* next = p->next;
        delete p;
        p = next;
    }
}
<|endoftext|>


<commit_before>#include "Homie.hpp"

using namespace HomieInternals;

SendingPromise::SendingPromise()
: _node(nullptr)
, _property(nullptr)
, _qos(0)
, _retained(false) {
}

SendingPromise& SendingPromise::setQos(uint8_t qos) {
  _qos = qos;
}

SendingPromise& SendingPromise::setRetained(bool retained) {
  _retained = retained;
}

SendingPromise& SendingPromise::setRange(const HomieRange& range) {
  _range = range;
}

SendingPromise& SendingPromise::setRange(uint16_t rangeIndex) {
  HomieRange range;
  range.isRange = true;
  range.index = rangeIndex;
  _range = range;
}

uint16_t SendingPromise::send(const String& value) {
  if (!Interface::get().connected) {
    Interface::get().getLogger() << F("✖ setNodeProperty(): impossible now") << endl;
    return 0;
  }

  char* topic = new char[strlen(Interface::get().getConfig().get().mqtt.baseTopic) + strlen(Interface::get().getConfig().get().deviceId) + 1 + strlen(_node->getId()) + 1 + strlen(_property->c_str()) + 6 + 1];  // last + 6 for range _65536
  strcpy(topic, Interface::get().getConfig().get().mqtt.baseTopic);
  strcat(topic, Interface::get().getConfig().get().deviceId);
  strcat_P(topic, PSTR("/"));
  strcat(topic, _node->getId());
  strcat_P(topic, PSTR("/"));
  strcat(topic, _property->c_str());

  if (_range.isRange) {
    char rangeStr[5 + 1];  // max 65536
    itoa(_range.index, rangeStr, 10);
    strcat_P(topic, PSTR("_"));
    strcat(topic, rangeStr);
  }

  uint16_t packetId = Interface::get().getMqttClient().publish(topic, _qos, _retained, value.c_str());
  delete[] topic;

  return packetId;
}

SendingPromise& SendingPromise::setNode(const HomieNode& node) {
  _node = &node;
}

SendingPromise& SendingPromise::setProperty(const String& property) {
  _property = &property;
}

const HomieNode* SendingPromise::getNode() const {
  return _node;
}

const String* SendingPromise::getProperty() const {
  return _property;
}

uint8_t SendingPromise::getQos() const {
  return _qos;
}

HomieRange SendingPromise::getRange() const {
  return _range;
}

bool SendingPromise::isRetained() const {
  return _retained;
}

HomieClass::HomieClass()
: _setupCalled(false)
, _firmwareSet(false)
, __HOMIE_SIGNATURE("\x25\x48\x4f\x4d\x49\x45\x5f\x45\x53\x50\x38\x32\x36\x36\x5f\x46\x57\x25") {
  strcpy(Interface::get().brand, DEFAULT_BRAND);
  Interface::get().standalone = false;
  Interface::get().led.enabled = true;
  Interface::get().led.pin = BUILTIN_LED;
  Interface::get().led.on = LOW;
  Interface::get().reset.idle = true;
  Interface::get().reset.enabled = true;
  Interface::get().reset.triggerPin = DEFAULT_RESET_PIN;
  Interface::get().reset.triggerState = DEFAULT_RESET_STATE;
  Interface::get().reset.triggerTime = DEFAULT_RESET_TIME;
  Interface::get().reset.flaggedBySketch = false;
  Interface::get().globalInputHandler = [](const HomieNode& node, const String& property, const HomieRange& range, const String& value) { return false; };
  Interface::get().broadcastHandler = [](const String& level, const String& value) { return false; };
  Interface::get().setupFunction = []() {};
  Interface::get().loopFunction = []() {};
  Interface::get().eventHandler = [](const HomieEvent& event) {};
  Interface::get().connected = false;
  Interface::get()._mqttClient = &_mqttClient;
  Interface::get()._blinker = &_blinker;
  Interface::get()._logger = &_logger;
  Interface::get()._config = &_config;

  DeviceId::generate();
}

HomieClass::~HomieClass() {
}

void HomieClass::_checkBeforeSetup(const __FlashStringHelper* functionName) {
  if (_setupCalled) {
    Interface::get().getLogger() << F("✖ ") << functionName << F("(): has to be called before setup()") << endl;
    Serial.flush();
    abort();
  }
}

void HomieClass::setup() {
  _setupCalled = true;

  if (!_firmwareSet) {
    Interface::get().getLogger() << F("✖ firmware must be set before calling setup()") << endl;
    Serial.flush();
    abort();
  }

  if (!Interface::get().getConfig().load()) {
    if (Interface::get().standalone && !Interface::get().getConfig().canBypassStandalone()) {
      _boot = &_bootStandalone;
      Interface::get().getLogger() << F("Triggering STANDALONE_MODE event...") << endl;
      Interface::get().event.type = HomieEventType::STANDALONE_MODE;
      Interface::get().eventHandler(Interface::get().event);
    } else {
      _boot = &_bootConfig;
      Interface::get().getLogger() << F("Triggering CONFIGURATION_MODE event...") << endl;
      Interface::get().event.type = HomieEventType::CONFIGURATION_MODE;
      Interface::get().eventHandler(Interface::get().event);
    }
  } else {
    switch (Interface::get().getConfig().getBootMode()) {
      case BootMode::NORMAL:
        _boot = &_bootNormal;
        Interface::get().getLogger() << F("Triggering NORMAL_MODE event...") << endl;
        Interface::get().event.type = HomieEventType::NORMAL_MODE;
        Interface::get().eventHandler(Interface::get().event);
        break;
      default:
        Interface::get().getLogger() << F("✖ The boot mode is invalid") << endl;
        Serial.flush();
        abort();
        break;
    }
  }

  _boot->setup();
}

void HomieClass::loop() {
  _boot->loop();
}

HomieClass& HomieClass::disableLogging() {
  _checkBeforeSetup(F("disableLogging"));

  Interface::get().getLogger().setLogging(false);

  return *this;
}

HomieClass& HomieClass::setLoggingPrinter(Print* printer) {
  _checkBeforeSetup(F("setLoggingPrinter"));

  Interface::get().getLogger().setPrinter(printer);

  return *this;
}

HomieClass& HomieClass::disableLedFeedback() {
  _checkBeforeSetup(F("disableLedFeedback"));

  Interface::get().led.enabled = false;

  return *this;
}

HomieClass& HomieClass::setLedPin(uint8_t pin, uint8_t on) {
  _checkBeforeSetup(F("setLedPin"));

  Interface::get().led.pin = pin;
  Interface::get().led.on = on;

  return *this;
}

void HomieClass::__setFirmware(const char* name, const char* version) {
  _checkBeforeSetup(F("setFirmware"));
  if (strlen(name) + 1 - 10 > MAX_FIRMWARE_NAME_LENGTH || strlen(version) + 1 - 10 > MAX_FIRMWARE_VERSION_LENGTH) {
    Interface::get().getLogger() << F("✖ setFirmware(): either the name or version string is too long") << endl;
    Serial.flush();
    abort();
  }

  strncpy(Interface::get().firmware.name, name + 5, strlen(name) - 10);
  Interface::get().firmware.name[strlen(name) - 10] = '\0';
  strncpy(Interface::get().firmware.version, version + 5, strlen(version) - 10);
  Interface::get().firmware.version[strlen(version) - 10] = '\0';
  _firmwareSet = true;
}

void HomieClass::__setBrand(const char* brand) {
  _checkBeforeSetup(F("setBrand"));
  if (strlen(brand) + 1 - 10 > MAX_BRAND_LENGTH) {
    Interface::get().getLogger() << F("✖ setBrand(): the brand string is too long") << endl;
    Serial.flush();
    abort();
  }

  strncpy(Interface::get().brand, brand + 5, strlen(brand) - 10);
  Interface::get().brand[strlen(brand) - 10] = '\0';
}

void HomieClass::reset() {
  Interface::get().reset.flaggedBySketch = true;
}

void HomieClass::setIdle(bool idle) {
  Interface::get().reset.idle = idle;
}

HomieClass& HomieClass::setGlobalInputHandler(GlobalInputHandler inputHandler) {
  _checkBeforeSetup(F("setGlobalInputHandler"));

  Interface::get().globalInputHandler = inputHandler;

  return *this;
}

HomieClass& HomieClass::setBroadcastHandler(BroadcastHandler broadcastHandler) {
  _checkBeforeSetup(F("setBroadcastHandler"));

  Interface::get().broadcastHandler = broadcastHandler;

  return *this;
}

HomieClass& HomieClass::setSetupFunction(OperationFunction function) {
  _checkBeforeSetup(F("setSetupFunction"));

  Interface::get().setupFunction = function;

  return *this;
}

HomieClass& HomieClass::setLoopFunction(OperationFunction function) {
  _checkBeforeSetup(F("setLoopFunction"));

  Interface::get().loopFunction = function;

  return *this;
}

HomieClass& HomieClass::setStandalone() {
  _checkBeforeSetup(F("setStandalone"));

  Interface::get().standalone = true;

  return *this;
}

bool HomieClass::isConfigured() const {
  return Interface::get().getConfig().getBootMode() == BootMode::NORMAL;
}

bool HomieClass::isConnected() const {
  return Interface::get().connected;
}

HomieClass& HomieClass::onEvent(EventHandler handler) {
  _checkBeforeSetup(F("onEvent"));

  Interface::get().eventHandler = handler;

  return *this;
}

HomieClass& HomieClass::setResetTrigger(uint8_t pin, uint8_t state, uint16_t time) {
  _checkBeforeSetup(F("setResetTrigger"));

  Interface::get().reset.enabled = true;
  Interface::get().reset.triggerPin = pin;
  Interface::get().reset.triggerState = state;
  Interface::get().reset.triggerTime = time;

  return *this;
}

HomieClass& HomieClass::disableResetTrigger() {
  _checkBeforeSetup(F("disableResetTrigger"));

  Interface::get().reset.enabled = false;

  return *this;
}

const ConfigStruct& HomieClass::getConfiguration() const {
  return Interface::get().getConfig().get();
}

AsyncMqttClient& HomieClass::getMqttClient() {
  return _mqttClient;
}

void HomieClass::prepareToSleep() {
  _boot->prepareToSleep();
}

HomieClass Homie;
<commit_msg>:bug: Fix explicit return of chainable API<commit_after>#include "Homie.hpp"

using namespace HomieInternals;

SendingPromise::SendingPromise()
: _node(nullptr)
, _property(nullptr)
, _qos(0)
, _retained(false) {
}

SendingPromise& SendingPromise::setQos(uint8_t qos) {
  _qos = qos;
  return *this;
}

SendingPromise& SendingPromise::setRetained(bool retained) {
  _retained = retained;
  return *this;
}

SendingPromise& SendingPromise::setRange(const HomieRange& range) {
  _range = range;
  return *this;
}

SendingPromise& SendingPromise::setRange(uint16_t rangeIndex) {
  HomieRange range;
  range.isRange = true;
  range.index = rangeIndex;
  _range = range;
  return *this;
}

uint16_t SendingPromise::send(const String& value) {
  if (!Interface::get().connected) {
    Interface::get().getLogger() << F("✖ setNodeProperty(): impossible now") << endl;
    return 0;
  }

  char* topic = new char[strlen(Interface::get().getConfig().get().mqtt.baseTopic) + strlen(Interface::get().getConfig().get().deviceId) + 1 + strlen(_node->getId()) + 1 + strlen(_property->c_str()) + 6 + 1];  // last + 6 for range _65536
  strcpy(topic, Interface::get().getConfig().get().mqtt.baseTopic);
  strcat(topic, Interface::get().getConfig().get().deviceId);
  strcat_P(topic, PSTR("/"));
  strcat(topic, _node->getId());
  strcat_P(topic, PSTR("/"));
  strcat(topic, _property->c_str());

  if (_range.isRange) {
    char rangeStr[5 + 1];  // max 65536
    itoa(_range.index, rangeStr, 10);
    strcat_P(topic, PSTR("_"));
    strcat(topic, rangeStr);
  }

  uint16_t packetId = Interface::get().getMqttClient().publish(topic, _qos, _retained, value.c_str());
  delete[] topic;

  return packetId;
}

SendingPromise& SendingPromise::setNode(const HomieNode& node) {
  _node = &node;
  return *this;
}

SendingPromise& SendingPromise::setProperty(const String& property) {
  _property = &property;
  return *this;
}

const HomieNode* SendingPromise::getNode() const {
  return _node;
}

const String* SendingPromise::getProperty() const {
  return _property;
}

uint8_t SendingPromise::getQos() const {
  return _qos;
}

HomieRange SendingPromise::getRange() const {
  return _range;
}

bool SendingPromise::isRetained() const {
  return _retained;
}

HomieClass::HomieClass()
: _setupCalled(false)
, _firmwareSet(false)
, __HOMIE_SIGNATURE("\x25\x48\x4f\x4d\x49\x45\x5f\x45\x53\x50\x38\x32\x36\x36\x5f\x46\x57\x25") {
  strcpy(Interface::get().brand, DEFAULT_BRAND);
  Interface::get().standalone = false;
  Interface::get().led.enabled = true;
  Interface::get().led.pin = BUILTIN_LED;
  Interface::get().led.on = LOW;
  Interface::get().reset.idle = true;
  Interface::get().reset.enabled = true;
  Interface::get().reset.triggerPin = DEFAULT_RESET_PIN;
  Interface::get().reset.triggerState = DEFAULT_RESET_STATE;
  Interface::get().reset.triggerTime = DEFAULT_RESET_TIME;
  Interface::get().reset.flaggedBySketch = false;
  Interface::get().globalInputHandler = [](const HomieNode& node, const String& property, const HomieRange& range, const String& value) { return false; };
  Interface::get().broadcastHandler = [](const String& level, const String& value) { return false; };
  Interface::get().setupFunction = []() {};
  Interface::get().loopFunction = []() {};
  Interface::get().eventHandler = [](const HomieEvent& event) {};
  Interface::get().connected = false;
  Interface::get()._mqttClient = &_mqttClient;
  Interface::get()._blinker = &_blinker;
  Interface::get()._logger = &_logger;
  Interface::get()._config = &_config;

  DeviceId::generate();
}

HomieClass::~HomieClass() {
}

void HomieClass::_checkBeforeSetup(const __FlashStringHelper* functionName) {
  if (_setupCalled) {
    Interface::get().getLogger() << F("✖ ") << functionName << F("(): has to be called before setup()") << endl;
    Serial.flush();
    abort();
  }
}

void HomieClass::setup() {
  _setupCalled = true;

  if (!_firmwareSet) {
    Interface::get().getLogger() << F("✖ firmware must be set before calling setup()") << endl;
    Serial.flush();
    abort();
  }

  if (!Interface::get().getConfig().load()) {
    if (Interface::get().standalone && !Interface::get().getConfig().canBypassStandalone()) {
      _boot = &_bootStandalone;
      Interface::get().getLogger() << F("Triggering STANDALONE_MODE event...") << endl;
      Interface::get().event.type = HomieEventType::STANDALONE_MODE;
      Interface::get().eventHandler(Interface::get().event);
    } else {
      _boot = &_bootConfig;
      Interface::get().getLogger() << F("Triggering CONFIGURATION_MODE event...") << endl;
      Interface::get().event.type = HomieEventType::CONFIGURATION_MODE;
      Interface::get().eventHandler(Interface::get().event);
    }
  } else {
    switch (Interface::get().getConfig().getBootMode()) {
      case BootMode::NORMAL:
        _boot = &_bootNormal;
        Interface::get().getLogger() << F("Triggering NORMAL_MODE event...") << endl;
        Interface::get().event.type = HomieEventType::NORMAL_MODE;
        Interface::get().eventHandler(Interface::get().event);
        break;
      default:
        Interface::get().getLogger() << F("✖ The boot mode is invalid") << endl;
        Serial.flush();
        abort();
        break;
    }
  }

  _boot->setup();
}

void HomieClass::loop() {
  _boot->loop();
}

HomieClass& HomieClass::disableLogging() {
  _checkBeforeSetup(F("disableLogging"));

  Interface::get().getLogger().setLogging(false);

  return *this;
}

HomieClass& HomieClass::setLoggingPrinter(Print* printer) {
  _checkBeforeSetup(F("setLoggingPrinter"));

  Interface::get().getLogger().setPrinter(printer);

  return *this;
}

HomieClass& HomieClass::disableLedFeedback() {
  _checkBeforeSetup(F("disableLedFeedback"));

  Interface::get().led.enabled = false;

  return *this;
}

HomieClass& HomieClass::setLedPin(uint8_t pin, uint8_t on) {
  _checkBeforeSetup(F("setLedPin"));

  Interface::get().led.pin = pin;
  Interface::get().led.on = on;

  return *this;
}

void HomieClass::__setFirmware(const char* name, const char* version) {
  _checkBeforeSetup(F("setFirmware"));
  if (strlen(name) + 1 - 10 > MAX_FIRMWARE_NAME_LENGTH || strlen(version) + 1 - 10 > MAX_FIRMWARE_VERSION_LENGTH) {
    Interface::get().getLogger() << F("✖ setFirmware(): either the name or version string is too long") << endl;
    Serial.flush();
    abort();
  }

  strncpy(Interface::get().firmware.name, name + 5, strlen(name) - 10);
  Interface::get().firmware.name[strlen(name) - 10] = '\0';
  strncpy(Interface::get().firmware.version, version + 5, strlen(version) - 10);
  Interface::get().firmware.version[strlen(version) - 10] = '\0';
  _firmwareSet = true;
}

void HomieClass::__setBrand(const char* brand) {
  _checkBeforeSetup(F("setBrand"));
  if (strlen(brand) + 1 - 10 > MAX_BRAND_LENGTH) {
    Interface::get().getLogger() << F("✖ setBrand(): the brand string is too long") << endl;
    Serial.flush();
    abort();
  }

  strncpy(Interface::get().brand, brand + 5, strlen(brand) - 10);
  Interface::get().brand[strlen(brand) - 10] = '\0';
}

void HomieClass::reset() {
  Interface::get().reset.flaggedBySketch = true;
}

void HomieClass::setIdle(bool idle) {
  Interface::get().reset.idle = idle;
}

HomieClass& HomieClass::setGlobalInputHandler(GlobalInputHandler inputHandler) {
  _checkBeforeSetup(F("setGlobalInputHandler"));

  Interface::get().globalInputHandler = inputHandler;

  return *this;
}

HomieClass& HomieClass::setBroadcastHandler(BroadcastHandler broadcastHandler) {
  _checkBeforeSetup(F("setBroadcastHandler"));

  Interface::get().broadcastHandler = broadcastHandler;

  return *this;
}

HomieClass& HomieClass::setSetupFunction(OperationFunction function) {
  _checkBeforeSetup(F("setSetupFunction"));

  Interface::get().setupFunction = function;

  return *this;
}

HomieClass& HomieClass::setLoopFunction(OperationFunction function) {
  _checkBeforeSetup(F("setLoopFunction"));

  Interface::get().loopFunction = function;

  return *this;
}

HomieClass& HomieClass::setStandalone() {
  _checkBeforeSetup(F("setStandalone"));

  Interface::get().standalone = true;

  return *this;
}

bool HomieClass::isConfigured() const {
  return Interface::get().getConfig().getBootMode() == BootMode::NORMAL;
}

bool HomieClass::isConnected() const {
  return Interface::get().connected;
}

HomieClass& HomieClass::onEvent(EventHandler handler) {
  _checkBeforeSetup(F("onEvent"));

  Interface::get().eventHandler = handler;

  return *this;
}

HomieClass& HomieClass::setResetTrigger(uint8_t pin, uint8_t state, uint16_t time) {
  _checkBeforeSetup(F("setResetTrigger"));

  Interface::get().reset.enabled = true;
  Interface::get().reset.triggerPin = pin;
  Interface::get().reset.triggerState = state;
  Interface::get().reset.triggerTime = time;

  return *this;
}

HomieClass& HomieClass::disableResetTrigger() {
  _checkBeforeSetup(F("disableResetTrigger"));

  Interface::get().reset.enabled = false;

  return *this;
}

const ConfigStruct& HomieClass::getConfiguration() const {
  return Interface::get().getConfig().get();
}

AsyncMqttClient& HomieClass::getMqttClient() {
  return _mqttClient;
}

void HomieClass::prepareToSleep() {
  _boot->prepareToSleep();
}

HomieClass Homie;
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Library
  Module:    MCubes.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include "MCubes.hh"
#include "MC_Cases.h"
#include "StrPts.hh"
#include "SScalars.hh"

// Description:
// Construct object with initial range (0,1) and single contour value
// of 0.0.
vlMarchingCubes::vlMarchingCubes()
{
  for (int i=0; i<MAX_CONTOURS; i++) this->Values[i] = 0.0;
  this->NumberOfContours = 1;
  this->Range[0] = 0.0;
  this->Range[1] = 1.0;
}

vlMarchingCubes::~vlMarchingCubes()
{
}

// Description:
// Set a particular contour value at contour number i.
void vlMarchingCubes::SetValue(int i, float value)
{
  i = (i >= MAX_CONTOURS ? MAX_CONTOURS-1 : (i < 0 ? 0 : i) );
  if ( this->Values[i] != value )
    {
    this->Modified();
    this->Values[i] = value;
    if ( i >= this->NumberOfContours ) this->NumberOfContours = i + 1;
    if ( value < this->Range[0] ) this->Range[0] = value;
    if ( value > this->Range[1] ) this->Range[1] = value;
    }
}

// Description:
// Generate numContours equally spaced contour values between specified
// range.
void vlMarchingCubes::GenerateValues(int numContours, float range[2])
{
  float val, incr;
  int i;

  numContours = (numContours > MAX_CONTOURS ? MAX_CONTOURS :
                 (numContours > 1 ? numContours : 2) );

  incr = (range[1] - range[0]) / (numContours-1);
  for (i=0, val=range[0]; i < numContours; i++, val+=incr)
    {
    this->SetValue(i,val);
    }
}

//
// Contouring filter specialized for volumes and "short int" data values.
//
void vlMarchingCubes::Execute()
{
  vlFloatPoints *newPts;
  vlCellArray *newPolys;
  vlStructuredPoints *input=(vlStructuredPoints *)this->Input;
  vlPointData *pd=input->GetPointData();
  vlScalars *inScalars=pd->GetScalars();
  short *scalars;
  int dims[3];

  vlDebugMacro(<< "Executing marching cubes");
  this->Initialize();
//
// Initialize and check input
//
  if ( inScalars == NULL )
    {
    vlErrorMacro(<<"Scalars must be defined for contouring");
    return;
    }

  if ( input->GetDataDimension() != 3 )
    {
    vlErrorMacro(<<"Cannot contour data of dimension != 3");
    return;
    }
  input->GetDimensions(dims);

  if ( strcmp("short",inScalars->GetDataType()) )
    {
    vlErrorMacro(<<"Scalars must be short ints...");
    return;
    }
  scalars = ((vlShortScalars *)inScalars)->GetPtr(0);
//
// Traverse all voxel cells, generating triangles and point normals
// using marching cubes algorithm.
//

  vlDebugMacro(<<"Created: "
               << newPts->GetNumberOfPoints() << " points, "
               << newPolys->GetNumberOfCells() << " triangles");
//
// Update ourselves.  Because we don't know up front how many verts, lines,
// polys we've created, take care to reclaim memory.
//
  this->SetPoints(newPts);
  this->SetPolys(newPolys);

  this->Squeeze();
}

void vlMarchingCubes::PrintSelf(ostream& os, vlIndent indent)
{
  int i;

  vlStructuredPointsToPolyDataFilter::PrintSelf(os,indent);

  os << indent << "Number Of Contours : " << this->NumberOfContours << "\n";
  os << indent << "Contour Values: \n";
  for ( i=0; i<this->NumberOfContours; i++)
    {
    os << indent << "  Value " << i << ": " << this->Values[i] << "\n";
    }
}

<commit_msg>ENH: Initial implementation.<commit_after>/*=========================================================================

  Program:   Visualization Library
  Module:    MCubes.cc
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

This file is part of the Visualization Library. No part of this file
or its contents may be copied, reproduced or altered in any way
without the express written consent of the authors.

Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 1993, 1994

=========================================================================*/
#include "MCubes.hh"
#include "MC_Cases.h"
#include "StrPts.hh"
#include "SScalars.hh"

// Description:
// Construct object with initial range (0,1) and single contour value
// of 0.0.
vlMarchingCubes::vlMarchingCubes()
{
  for (int i=0; i<MAX_CONTOURS; i++) this->Values[i] = 0.0;
  this->NumberOfContours = 1;
  this->Range[0] = 0.0;
  this->Range[1] = 1.0;
}

vlMarchingCubes::~vlMarchingCubes()
{
}

// Description:
// Set a particular contour value at contour number i.
void vlMarchingCubes::SetValue(int i, float value)
{
  i = (i >= MAX_CONTOURS ? MAX_CONTOURS-1 : (i < 0 ? 0 : i) );
  if ( this->Values[i] != value )
    {
    this->Modified();
    this->Values[i] = value;
    if ( i >= this->NumberOfContours ) this->NumberOfContours = i + 1;
    if ( value < this->Range[0] ) this->Range[0] = value;
    if ( value > this->Range[1] ) this->Range[1] = value;
    }
}

// Description:
// Generate numContours equally spaced contour values between specified
// range.
void vlMarchingCubes::GenerateValues(int numContours, float range[2])
{
  float val, incr;
  int i;

  numContours = (numContours > MAX_CONTOURS ? MAX_CONTOURS :
                 (numContours > 1 ? numContours : 2) );

  incr = (range[1] - range[0]) / (numContours-1);
  for (i=0, val=range[0]; i < numContours; i++, val+=incr)
    {
    this->SetValue(i,val);
    }
}

//
// Contouring filter specialized for volumes and "short int" data values.
//
void vlMarchingCubes::Execute()
{
  vlFloatPoints *newPts;
  vlCellArray *newPolys;
  vlShortScalars *newScalars;
  vlStructuredPoints *input=(vlStructuredPoints *)this->Input;
  vlPointData *pd=input->GetPointData();
  vlScalars *inScalars=pd->GetScalars();
  short *scalars, s[8], value;
  int dims[3];
  float ar[3], origin[3];
  int i, j, k, sliceSize;
  static int CASE_MASK[8] = {1,2,4,8,16,32,64,128};
  TRIANGLE_CASES *triCase;
  EDGE_LIST  *edge;
  int contNum, jOffset, kOffset, idx, ii, jj, index, *vert;
  int ptIds[3];
  float t, *x1, *x2, x[3];
  float pts[8][3];
  static int edges[12][2] = { {0,1}, {1,2}, {2,3}, {3,0},
                              {4,5}, {5,6}, {6,7}, {7,4},
                              {0,4}, {1,5}, {3,7}, {2,6}};

  vlDebugMacro(<< "Executing marching cubes");
  this->Initialize();
//
// Initialize and check input
//
  if ( inScalars == NULL )
    {
    vlErrorMacro(<<"Scalars must be defined for contouring");
    return;
    }

  if ( input->GetDataDimension() != 3 )
    {
    vlErrorMacro(<<"Cannot contour data of dimension != 3");
    return;
    }
  input->GetDimensions(dims);

  if ( strcmp("short",inScalars->GetDataType()) )
    {
    vlErrorMacro(<<"Scalars must be short ints...");
    return;
    }
  scalars = ((vlShortScalars *)inScalars)->GetPtr(0);

  newPts = new vlFloatPoints(10000,50000);
  newScalars = new vlShortScalars(10000,50000);
  newPolys = new vlCellArray();
  newPolys->Allocate(newPolys->EstimateSize(25000,3));
//
// Traverse all voxel cells, generating triangles and point normals
// using marching cubes algorithm.
//
  sliceSize = dims[0] * dims[1];
  for (contNum=0; contNum < this->NumberOfContours; contNum++)
    {
    value = (short) this->Values[contNum];
    for ( k=0; k < (dims[2]-1); k++)
      {
      kOffset = k*sliceSize;
      pts[0][2] = origin[2] + k*ar[2];
      for ( j=0; j < (dims[1]-1); j++)
        {
        jOffset = j*dims[0];
        pts[0][1] = origin[1] + j*ar[1];
        for ( i=0; i < (dims[0]-1); i++)
          {
          //get scalar values
          idx = i + jOffset + kOffset;
          s[0] = scalars[idx];
          s[1] = scalars[idx+1];
          s[2] = scalars[idx+1 + dims[0]];
          s[3] = scalars[idx + dims[0]];
          s[4] = scalars[idx + sliceSize];
          s[5] = scalars[idx+1 + sliceSize];
          s[6] = scalars[idx+1 + dims[0] + sliceSize];
          s[7] = scalars[idx + dims[0] + sliceSize];

          // Build the case table
          for ( ii=0, index = 0; ii < 8; ii++)
              if ( s[ii] >= value )
                  index |= CASE_MASK[i];

          if ( index == 0 || index == 255 ) continue; //no surface

          //create voxel points
          pts[0][0] = origin[0] + i*ar[0];

          pts[1][0] = pts[0][0] + ar[0];
          pts[1][1] = pts[0][1];
          pts[1][2] = pts[0][2];

          pts[2][0] = pts[0][0] + ar[0];
          pts[2][1] = pts[0][1] + ar[1];
          pts[2][2] = pts[0][2];

          pts[3][0] = pts[0][0];
          pts[3][1] = pts[0][1] + ar[1];
          pts[3][2] = pts[0][2];

          pts[4][0] = pts[0][0];
          pts[4][1] = pts[0][1];
          pts[4][2] = pts[0][2] + ar[2];

          pts[5][0] = pts[0][0] + ar[0];
          pts[5][1] = pts[0][1];
          pts[5][2] = pts[0][2] + ar[2];

          pts[6][0] = pts[0][0] + ar[0];
          pts[6][1] = pts[0][1] + ar[1];
          pts[6][2] = pts[0][2] + ar[2];

          pts[7][0] = pts[0][0];
          pts[7][1] = pts[0][1] + ar[1];
          pts[7][2] = pts[0][2] + ar[2];

          triCase = triCases + index;
          edge = triCase->edges;

          for ( ; edge[0] > -1; edge += 3 )
            {
            for (ii=0; ii<3; ii++) //insert triangle
              {
              vert = edges[edge[ii]];
              t = (value - s[vert[0]]) / (s[vert[1]] - s[vert[0]]);
              x1 = pts[vert[0]];
              x2 = pts[vert[1]];
              for (jj=0; jj<3; jj++) x[jj] = x1[jj] + t * (x2[jj] - x1[jj]);
              ptIds[ii] = newPts->InsertNextPoint(x);
              newScalars->InsertNextScalar(value);
              }
            newPolys->InsertNextCell(3,ptIds);
            }//for each triangle
          }//for i
        }//for j
      }//for k
    }//for all contours

  vlDebugMacro(<<"Created: "
               << newPts->GetNumberOfPoints() << " points, "
               << newPolys->GetNumberOfCells() << " triangles");
//
// Update ourselves.  Because we don't know up front how many triangles
// we've created, take care to reclaim memory.
//
  this->SetPoints(newPts);
  this->SetPolys(newPolys);
  this->PointData.SetScalars(newScalars);
  this->Squeeze();
}

void vlMarchingCubes::PrintSelf(ostream& os, vlIndent indent)
{
  int i;

  vlStructuredPointsToPolyDataFilter::PrintSelf(os,indent);

  os << indent << "Number Of Contours : " << this->NumberOfContours << "\n";
  os << indent << "Contour Values: \n";
  for ( i=0; i<this->NumberOfContours; i++)
    {
    os << indent << "  Value " << i << ": " << this->Values[i] << "\n";
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2013 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// exploitability_linux.cc: Linux specific exploitability engine.
//
// Provides a guess at the exploitability of the crash for the Linux
// platform given a minidump and process_state.
//
// Author: Matthew Riley

#include "processor/exploitability_linux.h"

#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/stack_frame.h"
#include "processor/logging.h"

namespace {

// This function in libc is called if the program was compiled with
// -fstack-protector and a function's stack canary changes.
const char kStackCheckFailureFunction[] = "__stack_chk_fail";

// This function in libc is called if the program was compiled with
// -D_FORTIFY_SOURCE=2, a function like strcpy() is called, and the runtime
// can determine that the call would overflow the target buffer.
const char kBoundsCheckFailureFunction[] = "__chk_fail";

}  // namespace

namespace google_breakpad {

ExploitabilityLinux::ExploitabilityLinux(Minidump *dump,
                                         ProcessState *process_state)
    : Exploitability(dump, process_state) { }

ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() {
  // Check the crashing thread for functions suggesting a buffer overflow or
  // stack smash.
  if (process_state_->requesting_thread() != -1) {
    CallStack* crashing_thread =
        process_state_->threads()->at(process_state_->requesting_thread());
    const vector<StackFrame*>& crashing_thread_frames =
        *crashing_thread->frames();
    for (size_t i = 0; i < crashing_thread_frames.size(); ++i) {
      if (crashing_thread_frames[i]->function_name ==
          kStackCheckFailureFunction) {
        return EXPLOITABILITY_HIGH;
      }

      if (crashing_thread_frames[i]->function_name ==
          kBoundsCheckFailureFunction) {
        return EXPLOITABILITY_HIGH;
      }
    }
  }

  // Check if the instruction pointer is in a valid instruction region
  // by finding if it maps to an executable part of memory.
  uint64_t instruction_ptr = 0;

  // Getting exception data. (It should exist for all minidumps.)
  MinidumpException *exception = dump_->GetException();
  if (exception == NULL) {
    BPLOG(INFO) << "No exception record.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }
  const MinidumpContext *context = exception->GetContext();
  if (context == NULL) {
    BPLOG(INFO) << "No exception context.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }

  // Getting instruction pointer based off architecture.
  uint32_t architecture = context->GetContextCPU();
  switch (architecture) {
    case MD_CONTEXT_X86:
      instruction_ptr = context->GetContextX86()->eip;
      break;
    case MD_CONTEXT_AMD64:
      instruction_ptr = context->GetContextAMD64()->rip;
      break;
    default:
      // TODO(liuandrew): Add support ARM and arm64 architectures.
      BPLOG(INFO) << "Unsupported architecture.";
      return EXPLOITABILITY_ERR_PROCESSING;
  }

  if (!this->InstructionPointerInCode(instruction_ptr)) {
    return EXPLOITABILITY_HIGH;
  }

  return EXPLOITABILITY_NONE;
}

bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) {
  // Here we get memory mapping. Most minidumps will not contain a memory
  // mapping, so we will commonly resort to checking modules.
  MinidumpMemoryInfoList *mem_info_list = dump_->GetMemoryInfoList();
  const MinidumpMemoryInfo *mem_info =
      mem_info_list ?
      mem_info_list->GetMemoryInfoForAddress(instruction_ptr) : NULL;

  // Checking if the memory mapping at the instruction pointer is executable.
  // If there is no memory mapping, we will use the modules as reference.
  if (mem_info != NULL) {
    return mem_info->IsExecutable();
  }

  // If the memory mapping retrieval fails, we will check the modules
  // to see if the instruction pointer is inside a module.
  // TODO(liuandrew): Check if the instruction pointer lies in an executable
  // region within the module.
  MinidumpModuleList *minidump_module_list = dump_->GetModuleList();
  return !minidump_module_list ||
          minidump_module_list->GetModuleForAddress(instruction_ptr);
}

}  // namespace google_breakpad
<commit_msg>This CL adds support for ARM and ARM64 architectures when calculating exploitability ratings.<commit_after>// Copyright (c) 2013 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

// exploitability_linux.cc: Linux specific exploitability engine.
//
// Provides a guess at the exploitability of the crash for the Linux
// platform given a minidump and process_state.
//
// Author: Matthew Riley

#include "processor/exploitability_linux.h"

#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/stack_frame.h"
#include "processor/logging.h"

namespace {

// This function in libc is called if the program was compiled with
// -fstack-protector and a function's stack canary changes.
const char kStackCheckFailureFunction[] = "__stack_chk_fail";

// This function in libc is called if the program was compiled with
// -D_FORTIFY_SOURCE=2, a function like strcpy() is called, and the runtime
// can determine that the call would overflow the target buffer.
const char kBoundsCheckFailureFunction[] = "__chk_fail";

}  // namespace

namespace google_breakpad {

ExploitabilityLinux::ExploitabilityLinux(Minidump *dump,
                                         ProcessState *process_state)
    : Exploitability(dump, process_state) { }

ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() {
  // Check the crashing thread for functions suggesting a buffer overflow or
  // stack smash.
  if (process_state_->requesting_thread() != -1) {
    CallStack* crashing_thread =
        process_state_->threads()->at(process_state_->requesting_thread());
    const vector<StackFrame*>& crashing_thread_frames =
        *crashing_thread->frames();
    for (size_t i = 0; i < crashing_thread_frames.size(); ++i) {
      if (crashing_thread_frames[i]->function_name ==
          kStackCheckFailureFunction) {
        return EXPLOITABILITY_HIGH;
      }

      if (crashing_thread_frames[i]->function_name ==
          kBoundsCheckFailureFunction) {
        return EXPLOITABILITY_HIGH;
      }
    }
  }

  // Check if the instruction pointer is in a valid instruction region
  // by finding if it maps to an executable part of memory.
  uint64_t instruction_ptr = 0;

  // Getting exception data. (It should exist for all minidumps.)
  MinidumpException *exception = dump_->GetException();
  if (exception == NULL) {
    BPLOG(INFO) << "No exception record.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }
  const MinidumpContext *context = exception->GetContext();
  if (context == NULL) {
    BPLOG(INFO) << "No exception context.";
    return EXPLOITABILITY_ERR_PROCESSING;
  }

  // Getting instruction pointer based off architecture.
  uint32_t architecture = context->GetContextCPU();
  switch (architecture) {
    case MD_CONTEXT_X86:
      instruction_ptr = context->GetContextX86()->eip;
      break;
    case MD_CONTEXT_AMD64:
      instruction_ptr = context->GetContextAMD64()->rip;
      break;
    case MD_CONTEXT_ARM:
      instruction_ptr =
          context->GetContextARM()->iregs[MD_CONTEXT_ARM_REG_PC];
      break;
    case MD_CONTEXT_ARM64:
      instruction_ptr =
          context->GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC];
      break;
    default:
      BPLOG(INFO) << "Unsupported architecture.";
      return EXPLOITABILITY_ERR_PROCESSING;
  }

  if (!this->InstructionPointerInCode(instruction_ptr)) {
    return EXPLOITABILITY_HIGH;
  }

  return EXPLOITABILITY_NONE;
}

bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) {
  // Here we get memory mapping. Most minidumps will not contain a memory
  // mapping, so we will commonly resort to checking modules.
  MinidumpMemoryInfoList *mem_info_list = dump_->GetMemoryInfoList();
  const MinidumpMemoryInfo *mem_info =
      mem_info_list ?
      mem_info_list->GetMemoryInfoForAddress(instruction_ptr) : NULL;

  // Checking if the memory mapping at the instruction pointer is executable.
  // If there is no memory mapping, we will use the modules as reference.
  if (mem_info != NULL) {
    return mem_info->IsExecutable();
  }

  // If the memory mapping retrieval fails, we will check the modules
  // to see if the instruction pointer is inside a module.
  // TODO(liuandrew): Check if the instruction pointer lies in an executable
  // region within the module.
  MinidumpModuleList *minidump_module_list = dump_->GetModuleList();
  return !minidump_module_list ||
          minidump_module_list->GetModuleForAddress(instruction_ptr);
}

}  // namespace google_breakpad
<|endoftext|>


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

#include "mime_handler.h"

#include <zorba/zorbastring.h>
#include <zorba/iterator.h>
#include <zorba/item_factory.h>
#include <zorba/store_consts.h>

namespace zorba
{
  namespace email
  {
  //helper function for retrieving the NodeName of an Item
  static zorba::String
  get_nodename(const Item aElement)
  {
    Item lNodeName;
    aElement.getNodeName(lNodeName);
    return lNodeName.getStringValue();
  }

  //helper function for retrieving the string value of a Text Node
  static void
  get_text_value(const Item aElement,
                  zorba::String& value)
  {
    Iterator_t lChildrenIt;
    Item       lChild;

    lChildrenIt = aElement.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild))
    {
      if (lChild.getNodeKind() == store::StoreConsts::textNode)
        value = lChild.getStringValue();
      else
        value = String();
    }
    lChildrenIt->close();
  }

  void CClientMimeHandler::begin(const Item& aMimeItem)
  {
    Iterator_t    childrenIt;

    //initialize ENVELOPE
    theEnvelope = mail_newenvelope ();

    //initialize BODY
    theBody = mail_newbody ();
    mail_initbody(theBody);

    //set theMessageItem
    childrenIt = aMimeItem.getChildren();
    childrenIt->open();
    if(childrenIt->next(theMessageItem))
      if (theMessageItem.getNodeKind() == store::StoreConsts::elementNode)
        if(!get_nodename(theMessageItem).lowercase().equals("message"))
          theMessageItem = zorba::Item();

    childrenIt->close();
  }

  bool
  CClientMimeHandler::envelope
      (zorba::String& aDiagnostics)
  {
    Iterator_t    lChildrenIt;
    zorba::Item   lChild;
    char line[MAILTMPLEN];
    bool          lRes = true;
    zorba::String lValue;

    if( theMessageItem.isNull() )
    {
      aDiagnostics = "The message could not be parsed.";
      return false;
    }

    //set the date from the client.
    //If this is not set it defaults to the date of the SMTP server.
    rfc822_date (line);
    theEnvelope->date = (unsigned char *) fs_get (1+strlen (line));
    strcpy ((char *)theEnvelope->date,line);

    lChildrenIt = theMessageItem.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild) && lRes)
    {
      if (lChild.getNodeKind() == store::StoreConsts::elementNode)
      {
        get_text_value(lChild, lValue);

        if(!lValue.empty())
        {
          zorba::String lLowerNodeName = get_nodename(lChild).lowercase();
          if(lLowerNodeName.equals("date"))
            theEnvelope->date = (unsigned char *) lValue.c_str();
          else if(lLowerNodeName.equals("from"))
          {
            theEnvelope->from = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->from, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("sender"))
          {
            theEnvelope->sender = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->sender, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("replyto"))
          {
            theEnvelope->reply_to = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->reply_to, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("subject"))
            theEnvelope->subject = cpystr ((char*)lValue.c_str());
          else if(lLowerNodeName.equals("to"))
          {
            theEnvelope->to = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->to, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("cc"))
          {
            theEnvelope->cc = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->cc, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("bcc"))
          {
            theEnvelope->bcc = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->bcc, (char*)lValue.c_str(), NIL);
          }
        }
      }
    }
    lChildrenIt->close();

    return lRes;
  }

  bool
  CClientMimeHandler::body
      (zorba::String& aDiagnostics)
  {
    Iterator_t    lChildrenIt;
    zorba::Item   lChild;
    bool          lRes = true;
    zorba::String lValue;

    theBody->type = TYPEOTHER;

    lChildrenIt = theMessageItem.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild))
    {
      if (lChild.getNodeKind() == store::StoreConsts::elementNode)
      {
        get_text_value(lChild, lValue);

        if(get_nodename(lChild).lowercase().equals("content"))
          parse_content(theBody, lChild);
        else if(get_nodename(lChild).lowercase().equals("multipart"))
          lRes = parse_multipart(theBody, lChild);
      }
    }
    lChildrenIt->close();

    return lRes;
  }

  void
  CClientMimeHandler::set_text_body
      (BODY* aBody,
       const char* aMessage)
  {
    aBody->contents.text.data = (unsigned char *) fs_get (8*MAILTMPLEN);   //message body
    sprintf ((char*)aBody->contents.text.data,"%s\015\012",aMessage);
    aBody->contents.text.size = strlen ((const char*)aBody->contents.text.data);
  }

  PARAMETER *
  CClientMimeHandler::create_param
      (const char* aAttribute,
       const char * aValue,
       PARAMETER * aPrevious)
  {
    PARAMETER *lParam;
    lParam = mail_newbody_parameter();
    lParam->attribute = cpystr (aAttribute);
    lParam->value = cpystr (aValue);

    if(aPrevious)
      aPrevious->next = lParam;

    return lParam;
  }

  void
  CClientMimeHandler::set_encoding
      (BODY* aBody,
       zorba::String& aEncoding)
  {
    //all encodings should start with ENC so we only check the rest of the string
    zorba::String lUpperEncSuffix = aEncoding.uppercase().substring(3);

    if(lUpperEncSuffix.equals("7BIT"))
      aBody->encoding = ENC7BIT;
    else if (lUpperEncSuffix.equals("8BIT"))
      aBody->encoding = ENC8BIT;
    else if (lUpperEncSuffix.equals("BINARY"))
      aBody->encoding = ENCBINARY;
    else if (lUpperEncSuffix.equals("BASE64"))
      aBody->encoding = ENCBASE64;
    else if (lUpperEncSuffix.equals("QUOTEDPRINTABLE"))
      aBody->encoding = ENCQUOTEDPRINTABLE;
    else
      aBody->encoding = ENCOTHER;
  }

  bool
  CClientMimeHandler::set_content_type_value
      (BODY* aBody,
       zorba::String& aValue)
  {
    bool          lRes = true;
    int           lPos = aValue.indexOf("/");
    zorba::String lLowerType = aValue.substring(0, lPos).lowercase();

    //set the BODY content type
    if(lLowerType.equals("text"))
      aBody->type = TYPETEXT;
    else if(lLowerType.equals("multipart"))
      aBody->type = TYPEMULTIPART;
    else if(lLowerType.equals("message"))
      aBody->type = TYPEMESSAGE;
    else if(lLowerType.equals("application"))
      aBody->type = TYPEAPPLICATION;
    else if(lLowerType.equals("image"))
      aBody->type = TYPEIMAGE;
    else if(lLowerType.equals("audio"))
      aBody->type = TYPEAUDIO;
    else if(lLowerType.equals("video"))
      aBody->type = TYPEVIDEO;
    else
    {
      aBody->type = TYPEOTHER;
      lRes = false;
    }
    if(lRes) //set the BODY content subtype
    {
      // the list of subtypes of each type is available at
      // http://www.iana.org/assignments/media-types/
      zorba::String lSubtype = aValue.substring(lPos + 1,aValue.length() - lPos);
      aBody->subtype = cpystr((char*) lSubtype.uppercase().c_str());
    }

    return lRes;
  }

  bool
  CClientMimeHandler::parse_content
      (BODY* aBody,
       const Item aItemContent)
  {
    Iterator_t    lChildrenIt;
    Item          lChild;
    zorba::String lNname, lValue;
    bool          lRes = true;

    PARAMETER* lRoot = NIL;
    PARAMETER* lPrev = NIL;

    lChildrenIt = aItemContent.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild) && lRes)
    {
      if (lChild.getNodeKind() == store::StoreConsts::elementNode)
      {
        lNname = get_nodename(lChild);
        get_text_value(lChild, lValue);
        if(lNname.lowercase().equals("contenttype"))
        {
          if(aBody->type == TYPEOTHER)
            lRes = set_content_type_value(aBody, lValue);
        }
        else if(lNname.lowercase().equals("charset"))
        {
          lRoot = create_param((char*)lNname.c_str(), (char*)lValue.uppercase().c_str(), NIL);
          lPrev = lRoot;
        }
        else if(lNname.lowercase().equals("contenttransferencoding"))
          set_encoding(aBody, lValue);
        //TODO: also parse the serialization attribute
        else if(lNname.lowercase().equals("body"))
          set_text_body(aBody, lValue.c_str());
        else
        {
          if(lNname.lowercase().equals("contentdisposition"))
            lNname = zorba::String("Content-Disposition");

          PARAMETER* lParam;
          lParam = create_param((char*)lNname.c_str(), (char*)lValue.lowercase().c_str(), lPrev);

          if(lPrev)
            lPrev->next = lParam;
          else
            lRoot = lParam;

          lPrev = lParam;
        }
      }
    }
    lChildrenIt->close();

    if(lRes && lRoot && lRoot->value)
      aBody->parameter = lRoot;

    return lRes;
  }

  bool
  CClientMimeHandler::parse_multipart
      (BODY* aBody,
       const Item aItemMultipart)
  {
    Iterator_t    lChildrenIt;
    Item          lChild;
    zorba::String lValue;
    bool          lRes = true;
    PART*         partRoot = NIL;
    PART*         partPrev = NIL;

    lChildrenIt = aItemMultipart.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild) && lRes)
    {
      if (lChild.getNodeKind() == store::StoreConsts::elementNode)
      {
        if(get_nodename(lChild).lowercase().equals("contenttype"))
        {
          get_text_value(lChild, lValue);
          if(aBody->type == TYPEOTHER)
            lRes = set_content_type_value(aBody, lValue);
        }
        else if(aBody->type == TYPEMULTIPART)
        {
          PART* part;
          part = NIL;
          part = mail_newbody_part();
          part->body.type = TYPEOTHER;

          lRes = parse_multipart(&part->body,lChild);

          if(partPrev)
            partPrev->next = part;
          else
            partRoot = part;

          partPrev = part;
        }
        else if((aBody->type != TYPEOTHER) &&
                (aBody->type != TYPEMULTIPART))
        {
          parse_content(aBody, aItemMultipart);
          break;
        }
      }
    }
    lChildrenIt->close();

    if(lRes && partRoot)
      aBody->nested.part = partRoot;

    return lRes;
  }

  //destroy theBody and theEnvelope
  void CClientMimeHandler::end()
  {
  }

  void
  CClientMimeHandler::CClientEnvelope
      (char* aFrom,
       char* aTo,
       char* aCc,
       char* aBcc,
       char* aSubject,
       char* aDate)
  {
    char line[MAILTMPLEN];

    theEnvelope->from = mail_newaddr ();
    theEnvelope->return_path = mail_newaddr ();

    if( aFrom )
      rfc822_parse_adrlist (&theEnvelope->from, (char*)aFrom, NIL);

    if( aTo )
      //Parse RFC 2822 address list
      rfc822_parse_adrlist (&theEnvelope->to, (char*)aTo, NIL);

    if( aCc )
      //Parse RFC 2822 address list
      rfc822_parse_adrlist (&theEnvelope->cc, (char*)aCc, NIL);

    if( aBcc )
      //Parse RFC 2822 address list
      rfc822_parse_adrlist (&theEnvelope->bcc, (char*)aBcc, NIL);

    if( aSubject )
      theEnvelope->subject = cpystr (aSubject);

    //set the date from the client.
    //if this is not set it defaults to the date of the SMTP server.
    if(aDate)
      theEnvelope->date = (unsigned char *)cpystr (aDate);
    else
    {
      rfc822_date (line);
      theEnvelope->date = (unsigned char *) fs_get (1+strlen (line));
      strcpy ((char *)theEnvelope->date,line);
    }
  }

  CClientMimeHandler::~CClientMimeHandler()
  {
    if( theEnvelope )
      mail_free_envelope( &theEnvelope );

    switch (theBody->type)
    {
      case TYPEMULTIPART:
        if(theBody->nested.part->body.parameter)
          mail_free_body_parameter(&theBody->nested.part->body.parameter);

        mail_free_body_part (&theBody->nested.part);
        break;
      default:
        break;
    }

    if(theBody->parameter)
      mail_free_body_parameter(&theBody->parameter);

    mail_free_body(&theBody);
  }

  }//namespace email
}//namespace zorba<commit_msg>Solved a problem in the 'get_text_value' and fixed the setting of the parameters for the emails with embedded images.<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <vector>

#include "mime_handler.h"

#include <zorba/zorbastring.h>
#include <zorba/iterator.h>
#include <zorba/item_factory.h>
#include <zorba/store_consts.h>

namespace zorba
{
  namespace email
  {
  //helper function for retrieving the NodeName of an Item
  static zorba::String
  get_nodename(const Item aElement)
  {
    Item lNodeName;
    aElement.getNodeName(lNodeName);
    return lNodeName.getStringValue();
  }

  //helper function for retrieving the string value of a Text Node
  static void
  get_text_value(const Item aElement,
                  zorba::String& aValue)
  {
    Iterator_t lChildrenIt;
    Item       lChild;

    aValue = String();

    lChildrenIt = aElement.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild))
      if (lChild.getNodeKind() == store::StoreConsts::textNode)
        aValue = lChild.getStringValue();

    lChildrenIt->close();
  }

  void CClientMimeHandler::begin(const Item& aMimeItem)
  {
    Iterator_t    childrenIt;

    //initialize ENVELOPE
    theEnvelope = mail_newenvelope ();

    //initialize BODY
    theBody = mail_newbody ();
    mail_initbody(theBody);

    //set theMessageItem
    childrenIt = aMimeItem.getChildren();
    childrenIt->open();
    if(childrenIt->next(theMessageItem))
      if (theMessageItem.getNodeKind() == store::StoreConsts::elementNode)
        if(!get_nodename(theMessageItem).lowercase().equals("message"))
          theMessageItem = zorba::Item();

    childrenIt->close();
  }

  bool
  CClientMimeHandler::envelope
      (zorba::String& aDiagnostics)
  {
    Iterator_t    lChildrenIt;
    zorba::Item   lChild;
    char line[MAILTMPLEN];
    bool          lRes = true;
    zorba::String lValue;

    if( theMessageItem.isNull() )
    {
      aDiagnostics = "The message could not be parsed.";
      return false;
    }

    //set the date from the client.
    //If this is not set it defaults to the date of the SMTP server.
    rfc822_date (line);
    theEnvelope->date = (unsigned char *) fs_get (1+strlen (line));
    strcpy ((char *)theEnvelope->date,line);

    lChildrenIt = theMessageItem.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild) && lRes)
    {
      if (lChild.getNodeKind() == store::StoreConsts::elementNode)
      {
        get_text_value(lChild, lValue);

        if(!lValue.empty())
        {
          zorba::String lLowerNodeName = get_nodename(lChild).lowercase();
          if(lLowerNodeName.equals("date"))
            theEnvelope->date = (unsigned char *) lValue.c_str();
          else if(lLowerNodeName.equals("from"))
          {
            theEnvelope->from = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->from, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("sender"))
          {
            theEnvelope->sender = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->sender, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("replyto"))
          {
            theEnvelope->reply_to = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->reply_to, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("subject"))
            theEnvelope->subject = cpystr ((char*)lValue.c_str());
          else if(lLowerNodeName.equals("to"))
          {
            theEnvelope->to = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->to, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("cc"))
          {
            theEnvelope->cc = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->cc, (char*)lValue.c_str(), NIL);
          }
          else if(lLowerNodeName.equals("bcc"))
          {
            theEnvelope->bcc = mail_newaddr ();
            rfc822_parse_adrlist (&theEnvelope->bcc, (char*)lValue.c_str(), NIL);
          }
        }
      }
    }
    lChildrenIt->close();

    return lRes;
  }

  bool
  CClientMimeHandler::body
      (zorba::String& aDiagnostics)
  {
    Iterator_t    lChildrenIt;
    zorba::Item   lChild;
    bool          lRes = true;
    zorba::String lValue;

    theBody->type = TYPEOTHER;

    lChildrenIt = theMessageItem.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild))
    {
      if (lChild.getNodeKind() == store::StoreConsts::elementNode)
      {
        get_text_value(lChild, lValue);

        if(get_nodename(lChild).lowercase().equals("content"))
          parse_content(theBody, lChild);
        else if(get_nodename(lChild).lowercase().equals("multipart"))
          lRes = parse_multipart(theBody, lChild);
      }
    }
    lChildrenIt->close();

    return lRes;
  }

  void
  CClientMimeHandler::set_text_body
      (BODY* aBody,
       const char* aMessage)
  {
    aBody->contents.text.data = (unsigned char *) fs_get (8*MAILTMPLEN);   //message body
    sprintf ((char*)aBody->contents.text.data,"%s\015\012",aMessage);
    aBody->contents.text.size = strlen ((const char*)aBody->contents.text.data);
  }

  PARAMETER *
  CClientMimeHandler::create_param
      (const char* aAttribute,
       const char * aValue,
       PARAMETER * aPrevious)
  {
    PARAMETER *lParam;
    lParam = mail_newbody_parameter();
    lParam->attribute = cpystr (aAttribute);
    lParam->value = cpystr (aValue);

    if(aPrevious)
      aPrevious->next = lParam;

    return lParam;
  }

  void
  CClientMimeHandler::set_encoding
      (BODY* aBody,
       zorba::String& aEncoding)
  {
    //all encodings should start with ENC so we only check the rest of the string
    zorba::String lUpperEncSuffix = aEncoding.uppercase().substring(3);

    if(lUpperEncSuffix.equals("7BIT"))
      aBody->encoding = ENC7BIT;
    else if (lUpperEncSuffix.equals("8BIT"))
      aBody->encoding = ENC8BIT;
    else if (lUpperEncSuffix.equals("BINARY"))
      aBody->encoding = ENCBINARY;
    else if (lUpperEncSuffix.equals("BASE64"))
      aBody->encoding = ENCBASE64;
    else if (lUpperEncSuffix.equals("QUOTEDPRINTABLE"))
      aBody->encoding = ENCQUOTEDPRINTABLE;
    else
      aBody->encoding = ENCOTHER;
  }

  bool
  CClientMimeHandler::set_content_type_value
      (BODY* aBody,
       zorba::String& aValue)
  {
    bool          lRes = true;
    int           lPos = aValue.indexOf("/");
    zorba::String lLowerType = aValue.substring(0, lPos).lowercase();

    //set the BODY content type
    if(lLowerType.equals("text"))
      aBody->type = TYPETEXT;
    else if(lLowerType.equals("multipart"))
      aBody->type = TYPEMULTIPART;
    else if(lLowerType.equals("message"))
      aBody->type = TYPEMESSAGE;
    else if(lLowerType.equals("application"))
      aBody->type = TYPEAPPLICATION;
    else if(lLowerType.equals("image"))
      aBody->type = TYPEIMAGE;
    else if(lLowerType.equals("audio"))
      aBody->type = TYPEAUDIO;
    else if(lLowerType.equals("video"))
      aBody->type = TYPEVIDEO;
    else
    {
      aBody->type = TYPEOTHER;
      lRes = false;
    }
    if(lRes) //set the BODY content subtype
    {
      // the list of subtypes of each type is available at
      // http://www.iana.org/assignments/media-types/
      zorba::String lSubtype = aValue.substring(lPos + 1,aValue.length() - lPos);
      aBody->subtype = cpystr((char*) lSubtype.uppercase().c_str());
    }

    return lRes;
  }

  bool
  CClientMimeHandler::parse_content
      (BODY* aBody,
       const Item aItemContent)
  {
    Iterator_t    lChildrenIt;
    Item          lChild;
    zorba::String lNname, lValue;
    bool          lRes = true;

    PARAMETER* lRoot = NIL;
    PARAMETER* lPrev = NIL;

    lChildrenIt = aItemContent.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild) && lRes)
    {
      if (lChild.getNodeKind() == store::StoreConsts::elementNode)
      {
        lNname = get_nodename(lChild);
        get_text_value(lChild, lValue);
        if(lNname.lowercase().equals("contenttype"))
        {
          if(aBody->type == TYPEOTHER)
            lRes = set_content_type_value(aBody, lValue);
        }
        else if(lNname.lowercase().equals("charset") ||
                lNname.lowercase().equals("name"))
        {
          lRoot = create_param((char*)lNname.c_str(), (char*)lValue.uppercase().c_str(), NIL);
          lPrev = lRoot;
        }
        else if(lNname.lowercase().equals("contenttransferencoding"))
          set_encoding(aBody, lValue);
        else if(lNname.lowercase().equals("body"))
          set_text_body(aBody, lValue.c_str());
        else if(lNname.lowercase().equals("content-id"))
          aBody->id = cpystr((char*)lValue.lowercase().c_str());
        else if(lNname.lowercase().equals("content-disposition"))
          //defined at http://tools.ietf.org/html/rfc2183 ,only FILENAME is parsed
          aBody->disposition.type = cpystr((char*)lValue.uppercase().c_str());
        else if(lNname.lowercase().equals("filename"))
        {
          PARAMETER* lfilename = NIL;
          lfilename = create_param((char*)lNname.c_str(), (char*)lValue.c_str(), NIL);
          aBody->disposition.parameter = lfilename;
        }
        else
        {
          PARAMETER* lParam = NIL;
          lParam = create_param((char*)lNname.c_str(), (char*)lValue.lowercase().c_str(), lPrev);

          if(lPrev)
            lPrev->next = lParam;
          else
            lRoot = lParam;

          lPrev = lParam;
        }
      }
    }
    lChildrenIt->close();

    if(lRes && lRoot && lRoot->value)
      aBody->parameter = lRoot;

    return lRes;
  }

  bool
  CClientMimeHandler::parse_multipart
      (BODY* aBody,
       const Item aItemMultipart)
  {
    Iterator_t    lChildrenIt;
    Item          lChild;
    zorba::String lValue;
    bool          lRes = true;
    PART*         partRoot = NIL;
    PART*         partPrev = NIL;

    lChildrenIt = aItemMultipart.getChildren();
    lChildrenIt->open();
    while (lChildrenIt->next(lChild) && lRes)
    {
      if (lChild.getNodeKind() == store::StoreConsts::elementNode)
      {
        if(get_nodename(lChild).lowercase().equals("contenttype"))
        {
          get_text_value(lChild, lValue);
          if(aBody->type == TYPEOTHER)
            lRes = set_content_type_value(aBody, lValue);
        }
        else if(aBody->type == TYPEMULTIPART)
        {
          PART* part;
          part = NIL;
          part = mail_newbody_part();
          part->body.type = TYPEOTHER;

          lRes = parse_multipart(&part->body,lChild);

          if(partPrev)
            partPrev->next = part;
          else
            partRoot = part;

          partPrev = part;
        }
        else if((aBody->type != TYPEOTHER) &&
                (aBody->type != TYPEMULTIPART))
        {
          parse_content(aBody, aItemMultipart);
          break;
        }
      }
    }
    lChildrenIt->close();

    if(lRes && partRoot)
      aBody->nested.part = partRoot;

    return lRes;
  }

  //destroy theBody and theEnvelope
  void CClientMimeHandler::end()
  {
  }

  void
  CClientMimeHandler::CClientEnvelope
      (char* aFrom,
       char* aTo,
       char* aCc,
       char* aBcc,
       char* aSubject,
       char* aDate)
  {
    char line[MAILTMPLEN];

    theEnvelope->from = mail_newaddr ();
    theEnvelope->return_path = mail_newaddr ();

    if( aFrom )
      rfc822_parse_adrlist (&theEnvelope->from, (char*)aFrom, NIL);

    if( aTo )
      //Parse RFC 2822 address list
      rfc822_parse_adrlist (&theEnvelope->to, (char*)aTo, NIL);

    if( aCc )
      //Parse RFC 2822 address list
      rfc822_parse_adrlist (&theEnvelope->cc, (char*)aCc, NIL);

    if( aBcc )
      //Parse RFC 2822 address list
      rfc822_parse_adrlist (&theEnvelope->bcc, (char*)aBcc, NIL);

    if( aSubject )
      theEnvelope->subject = cpystr (aSubject);

    //set the date from the client.
    //if this is not set it defaults to the date of the SMTP server.
    if(aDate)
      theEnvelope->date = (unsigned char *)cpystr (aDate);
    else
    {
      rfc822_date (line);
      theEnvelope->date = (unsigned char *) fs_get (1+strlen (line));
      strcpy ((char *)theEnvelope->date,line);
    }
  }

  CClientMimeHandler::~CClientMimeHandler()
  {
    if( theEnvelope )
      mail_free_envelope( &theEnvelope );

    mail_free_body(&theBody);
  }

  }//namespace email
}//namespace zorba<|endoftext|>