<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2021 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

#ifndef BATTERY_STATUS_HPP
#define BATTERY_STATUS_HPP

#include <uORB/topics/battery_status.h>

class MavlinkStreamBatteryStatus : public MavlinkStream
{
public:
	static MavlinkStream *new_instance(Mavlink *mavlink) { return new MavlinkStreamBatteryStatus(mavlink); }

	static constexpr const char *get_name_static() { return "BATTERY_STATUS"; }
	static constexpr uint16_t get_id_static() { return MAVLINK_MSG_ID_BATTERY_STATUS; }

	const char *get_name() const override { return get_name_static(); }
	uint16_t get_id() override { return get_id_static(); }

	unsigned get_size() override
	{
		static constexpr unsigned size_per_battery = MAVLINK_MSG_ID_BATTERY_STATUS_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES;
		return size_per_battery * _battery_status_subs.advertised_count();
	}

private:
	explicit MavlinkStreamBatteryStatus(Mavlink *mavlink) : MavlinkStream(mavlink) {}

	uORB::SubscriptionMultiArray<battery_status_s, battery_status_s::MAX_INSTANCES> _battery_status_subs{ORB_ID::battery_status};

	bool send() override
	{
		bool updated = false;

		for (auto &battery_sub : _battery_status_subs) {
			battery_status_s battery_status;

			if (battery_sub.update(&battery_status)) {
				/* battery status message with higher resolution */
				mavlink_battery_status_t bat_msg{};
				// TODO: Determine how to better map between battery ID within the firmware and in MAVLink
				bat_msg.id = battery_status.id - 1;
				bat_msg.battery_function = MAV_BATTERY_FUNCTION_ALL;
				bat_msg.type = MAV_BATTERY_TYPE_LIPO;
				bat_msg.current_consumed = (battery_status.connected) ? battery_status.discharged_mah : -1;
				bat_msg.energy_consumed = -1;
				bat_msg.current_battery = (battery_status.connected) ? battery_status.current_filtered_a * 100 : -1;
				bat_msg.battery_remaining = (battery_status.connected) ? ceilf(battery_status.remaining * 100.f) : -1;
				bat_msg.time_remaining = (battery_status.connected) ? battery_status.run_time_to_empty * 60 : 0;

				switch (battery_status.warning) {
				case (battery_status_s::BATTERY_WARNING_NONE):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_OK;
					break;

				case (battery_status_s::BATTERY_WARNING_LOW):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_LOW;
					break;

				case (battery_status_s::BATTERY_WARNING_CRITICAL):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_CRITICAL;
					break;

				case (battery_status_s::BATTERY_WARNING_EMERGENCY):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_EMERGENCY;
					break;

				case (battery_status_s::BATTERY_WARNING_FAILED):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_FAILED;
					break;

				default:
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_UNDEFINED;
					break;
				}

				// check if temperature valid
				if (battery_status.connected && PX4_ISFINITE(battery_status.temperature)) {
					bat_msg.temperature = battery_status.temperature * 100.f;

				} else {
					bat_msg.temperature = INT16_MAX;
				}

				static constexpr int mavlink_cells_max = (sizeof(bat_msg.voltages) / sizeof(bat_msg.voltages[0]));
				static constexpr int uorb_cells_max =
					(sizeof(battery_status.voltage_cell_v) / sizeof(battery_status.voltage_cell_v[0]));

				for (int cell = 0; cell < mavlink_cells_max; cell++) {
					if (battery_status.connected && (cell < battery_status.cell_count) && (cell < uorb_cells_max)) {
						bat_msg.voltages[cell] = battery_status.voltage_cell_v[cell] * 1000.f;

					} else {
						bat_msg.voltages[cell] = UINT16_MAX;
					}
				}

				mavlink_msg_battery_status_send_struct(_mavlink->get_channel(), &bat_msg);
				updated = true;
			}
		}

		return updated;
	}
};

#endif // BATTERY_STATUS_HPP
<commit_msg>mavlink: 14S battery support<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2021 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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.
 *
 ****************************************************************************/

#ifndef BATTERY_STATUS_HPP
#define BATTERY_STATUS_HPP

#include <uORB/topics/battery_status.h>

class MavlinkStreamBatteryStatus : public MavlinkStream
{
public:
	static MavlinkStream *new_instance(Mavlink *mavlink) { return new MavlinkStreamBatteryStatus(mavlink); }

	static constexpr const char *get_name_static() { return "BATTERY_STATUS"; }
	static constexpr uint16_t get_id_static() { return MAVLINK_MSG_ID_BATTERY_STATUS; }

	const char *get_name() const override { return get_name_static(); }
	uint16_t get_id() override { return get_id_static(); }

	unsigned get_size() override
	{
		static constexpr unsigned size_per_battery = MAVLINK_MSG_ID_BATTERY_STATUS_LEN + MAVLINK_NUM_NON_PAYLOAD_BYTES;
		return size_per_battery * _battery_status_subs.advertised_count();
	}

private:
	explicit MavlinkStreamBatteryStatus(Mavlink *mavlink) : MavlinkStream(mavlink) {}

	uORB::SubscriptionMultiArray<battery_status_s, battery_status_s::MAX_INSTANCES> _battery_status_subs{ORB_ID::battery_status};

	bool send() override
	{
		bool updated = false;

		for (auto &battery_sub : _battery_status_subs) {
			battery_status_s battery_status;

			if (battery_sub.update(&battery_status)) {
				/* battery status message with higher resolution */
				mavlink_battery_status_t bat_msg{};
				// TODO: Determine how to better map between battery ID within the firmware and in MAVLink
				bat_msg.id = battery_status.id - 1;
				bat_msg.battery_function = MAV_BATTERY_FUNCTION_ALL;
				bat_msg.type = MAV_BATTERY_TYPE_LIPO;
				bat_msg.current_consumed = (battery_status.connected) ? battery_status.discharged_mah : -1;
				bat_msg.energy_consumed = -1;
				bat_msg.current_battery = (battery_status.connected) ? battery_status.current_filtered_a * 100 : -1;
				bat_msg.battery_remaining = (battery_status.connected) ? ceilf(battery_status.remaining * 100.f) : -1;
				bat_msg.time_remaining = (battery_status.connected) ? battery_status.run_time_to_empty * 60 : 0;

				switch (battery_status.warning) {
				case (battery_status_s::BATTERY_WARNING_NONE):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_OK;
					break;

				case (battery_status_s::BATTERY_WARNING_LOW):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_LOW;
					break;

				case (battery_status_s::BATTERY_WARNING_CRITICAL):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_CRITICAL;
					break;

				case (battery_status_s::BATTERY_WARNING_EMERGENCY):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_EMERGENCY;
					break;

				case (battery_status_s::BATTERY_WARNING_FAILED):
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_FAILED;
					break;

				default:
					bat_msg.charge_state = MAV_BATTERY_CHARGE_STATE_UNDEFINED;
					break;
				}

				// check if temperature valid
				if (battery_status.connected && PX4_ISFINITE(battery_status.temperature)) {
					bat_msg.temperature = battery_status.temperature * 100.f;

				} else {
					bat_msg.temperature = INT16_MAX;
				}

				static constexpr int mavlink_cells_max = (sizeof(bat_msg.voltages) / sizeof(bat_msg.voltages[0]));
				static constexpr int uorb_cells_max =
					(sizeof(battery_status.voltage_cell_v) / sizeof(battery_status.voltage_cell_v[0]));

				for (int cell = 0; cell < mavlink_cells_max; cell++) {
					if (battery_status.connected && (cell < battery_status.cell_count) && (cell < uorb_cells_max)) {
						bat_msg.voltages[cell] = battery_status.voltage_cell_v[cell] * 1000.f;

					} else {
						bat_msg.voltages[cell] = UINT16_MAX;
					}
				}

				static constexpr int mavlink_cells_ext_max = (sizeof(bat_msg.voltages_ext) / sizeof(bat_msg.voltages_ext[0]));

				for (int cell = mavlink_cells_max; cell < mavlink_cells_max + mavlink_cells_ext_max; cell++) {
					if (battery_status.connected && (cell < battery_status.cell_count) && (cell < uorb_cells_max)) {
						bat_msg.voltages_ext[cell - mavlink_cells_max] = battery_status.voltage_cell_v[cell] * 1000.0f;

					} else {
						bat_msg.voltages_ext[cell - mavlink_cells_max] = UINT16_MAX;
					}
				}

				mavlink_msg_battery_status_send_struct(_mavlink->get_channel(), &bat_msg);
				updated = true;
			}
		}

		return updated;
	}
};

#endif // BATTERY_STATUS_HPP
<|endoftext|>


<commit_before>// -*-c++-*-

/*
 * $Id$
 *
 * DirectX file converter for OpenSceneGraph.
 * Copyright (c)2002 Ulrich Hertlein <u.hertlein@sandbox.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "directx.h"

#include <string>

#include <osg/TexEnv>
#include <osg/CullFace>

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/Image>
#include <osg/Texture2D>

#include <osg/Notify>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileNameUtils>

/**
 * OpenSceneGraph plugin wrapper/converter.
 */
class ReaderWriterDirectX : public osgDB::ReaderWriter
{
public:
    ReaderWriterDirectX() { }

    virtual const char* className() {
        return "DirectX Reader/Writer";
    }

    virtual bool acceptsExtension(const std::string& extension) {
        return osgDB::equalCaseInsensitive(extension,"x") ? true : false;
    }

    virtual ReadResult readNode(const std::string& fileName,
                                const osgDB::ReaderWriter::Options* options);

private:
    osg::Geode* convertFromDX(DX::Object& obj, bool flipTexture, float creaseAngle);
};

// Register with Registry to instantiate the above reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterDirectX> g_readerWriter_DirectX_Proxy;

// Read node
osgDB::ReaderWriter::ReadResult ReaderWriterDirectX::readNode(const std::string& fileName,
                                                              const osgDB::ReaderWriter::Options* options)
{
    std::string ext = osgDB::getLowerCaseFileExtension(fileName);
    if (!acceptsExtension(ext))
        return ReadResult::FILE_NOT_HANDLED;

    osg::notify(osg::INFO) << "ReaderWriterDirectX::readNode(" << fileName.c_str() << ")\n";

    // Load DirectX mesh
    DX::Object obj;
    if (obj.load(fileName.c_str())) {

        // Options?
        bool flipTexture = true;
        float creaseAngle = 80.0f;
        if (options) {
            const std::string option = options->getOptionString();
            if (option.find("flipTexture") != string::npos)
                flipTexture = false;
            if (option.find("creaseAngle") != string::npos) {
                // TODO
            }
        }

        // Convert to osg::Geode
        osg::Geode* geode = convertFromDX(obj, flipTexture, creaseAngle);
        if (!geode)
            return ReadResult::FILE_NOT_HANDLED;

        return geode;
    }

    return ReadResult::FILE_NOT_HANDLED;
}

// Convert DirectX mesh to osg::Geode
osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Object& obj,
                                               bool flipTexture, float creaseAngle)
{
    // Fetch mesh
    const DX::Mesh* mesh = obj.getMesh();
    if (!mesh)
        return NULL;

    const DX::MeshMaterialList* meshMaterial = obj.getMeshMaterialList();
    if (!meshMaterial)
        return NULL;

    const DX::MeshNormals* meshNormals = obj.getMeshNormals();
    if (!meshNormals) {
        obj.generateNormals(creaseAngle);
        meshNormals = obj.getMeshNormals();
    }
    if (!meshNormals)
        return NULL;

    const DX::MeshTextureCoords* meshTexCoords = obj.getMeshTextureCoords();
    if (!meshTexCoords)
        return NULL;

    /*
     * - MeshMaterialList contains a list of Material and a per-face
     *   information with Material is to be applied to which face.
     * - Mesh contains a list of Vertices and a per-face information
     *   which vertices (three or four) belong to this face.
     * - MeshNormals contains a list of Normals and a per-face information
     *   which normal is used by which vertex.
     * - MeshTextureCoords contains a list of per-vertex texture coordinates.
     *
     * - Uses left-hand CS with Y-up, Z-into
     *   obj_x -> osg_x
     *   obj_y -> osg_z
     *   obj_z -> osg_y
     *
     * - Polys are CW oriented
     */
    vector<osg::Geometry*> geomList;

    unsigned int i;
    for (i = 0; i < meshMaterial->material.size(); i++) {

        const DX::Material& mtl = meshMaterial->material[i];
        osg::StateSet* state = new osg::StateSet;

        // Material
        osg::Material* material = new osg::Material;
        state->setAttributeAndModes(material);

        float alpha = mtl.faceColor.alpha;
        osg::Vec4 ambient(mtl.faceColor.red,
                          mtl.faceColor.green,
                          mtl.faceColor.blue,
                          alpha);
        material->setAmbient(osg::Material::FRONT, ambient);
        material->setDiffuse(osg::Material::FRONT, ambient);

        material->setShininess(osg::Material::FRONT, mtl.power);

        osg::Vec4 specular(mtl.specularColor.red,
                           mtl.specularColor.green,
                           mtl.specularColor.blue, alpha);
        material->setSpecular(osg::Material::FRONT, specular);

        osg::Vec4 emissive(mtl.emissiveColor.red,
                           mtl.emissiveColor.green,
                           mtl.emissiveColor.blue, alpha);
        material->setEmission(osg::Material::FRONT, emissive);

        // Transparency? Set render hint & blending
        if (alpha < 1.0f) {
            state->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
            state->setMode(GL_BLEND, osg::StateAttribute::ON);
        }
        else
            state->setMode(GL_BLEND, osg::StateAttribute::OFF);

        unsigned int textureCount = mtl.texture.size();
        for (unsigned int j = 0; j < textureCount; j++) {
            // Load image
            osg::Image* image = osgDB::readImageFile(mtl.texture[j]);
            if (!image)
                continue;

            // Texture
            osg::Texture2D* texture = new osg::Texture2D;
            texture->setImage(image);
            texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
            texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
            state->setTextureAttributeAndModes(j, texture);
        }

        // Geometry
        osg::Geometry* geom = new osg::Geometry;
        geomList.push_back(geom);

        geom->setStateSet(state);

        // Arrays to hold vertices, normals, and texcoords.
        geom->setVertexArray(new osg::Vec3Array);
        geom->setNormalArray(new osg::Vec3Array);
        geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
        if (textureCount) {
            // All texture units share the same array
            osg::Vec2Array* texCoords = new osg::Vec2Array;
            for (unsigned int j = 0; j < textureCount; j++)
                geom->setTexCoordArray(j, texCoords);
        }

        geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON));
    }

    assert(mesh->faces.size() == meshMaterial->faceIndices.size());

    // Add faces to Geometry
    for (i = 0; i < meshMaterial->faceIndices.size(); i++) {

        // Geometry for Material
        unsigned int mi = meshMaterial->faceIndices[i];
        osg::Geometry* geom = geomList[mi];

        // #pts of this face
        unsigned int np = mesh->faces[i].size();
        ((osg::DrawArrayLengths*) geom->getPrimitiveSet(0))->push_back(np);

        assert(np == meshNormals->faceNormals[i].size());

        osg::Vec3Array* vertexArray = (osg::Vec3Array*) geom->getVertexArray();
        osg::Vec3Array* normalArray = (osg::Vec3Array*) geom->getNormalArray();
        osg::Vec2Array* texCoordArray = (osg::Vec2Array*) geom->getTexCoordArray(0);

        // Add vertices, normals, texcoords
        for (unsigned int j = 0; j < np; j++) {

            // Convert CW to CCW order
            unsigned int jj = (j > 0 ? np - j : j);

            // Vertices
            unsigned int vi = mesh->faces[i][jj];
            if (vertexArray) {
                // Transform Xleft/Yup/Zinto to Xleft/Yinto/Zup
                const DX::Vector& v = mesh->vertices[vi];
                vertexArray->push_back(osg::Vec3(v.x,v.z,v.y));
            }

            // Normals
            unsigned int ni = meshNormals->faceNormals[i][jj];
            if (normalArray) {
                // Transform Xleft/Yup/Zinto to Xleft/Yinto/Zup
                const DX::Vector& n = meshNormals->normals[ni];
                normalArray->push_back(osg::Vec3(n.x,n.z,n.y));
            }

            // TexCoords
            if (texCoordArray) {
                const DX::Coords2d& tc = (*meshTexCoords)[vi];
                osg::Vec2 uv;
                if (flipTexture)
                    uv.set(tc.u, 1.0f - tc.v); // Image is upside down
                else
                    uv.set(tc.u, tc.v);
                texCoordArray->push_back(uv);
            }
        }
    }

    // Add non-empty nodes to Geode
    osg::Geode* geode = new osg::Geode;
    for (i = 0; i < geomList.size(); i++) {
        osg::Geometry* geom = geomList[i];
        if (((osg::Vec3Array*) geom->getVertexArray())->size())
            geode->addDrawable(geom);
    }

    // Back-face culling
    osg::StateSet* state = new osg::StateSet;
    geode->setStateSet(state);

    osg::CullFace* cullFace = new osg::CullFace;
    cullFace->setMode(osg::CullFace::BACK);
    state->setAttributeAndModes(cullFace);

    return geode;
}
<commit_msg>ReaderWriterDirectX.cpp needed some std::'s<commit_after>// -*-c++-*-

/*
 * $Id$
 *
 * DirectX file converter for OpenSceneGraph.
 * Copyright (c)2002 Ulrich Hertlein <u.hertlein@sandbox.de>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "directx.h"

#include <string>

#include <osg/TexEnv>
#include <osg/CullFace>

#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/Image>
#include <osg/Texture2D>

#include <osg/Notify>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/FileNameUtils>

/**
 * OpenSceneGraph plugin wrapper/converter.
 */
class ReaderWriterDirectX : public osgDB::ReaderWriter
{
public:
    ReaderWriterDirectX() { }

    virtual const char* className() {
        return "DirectX Reader/Writer";
    }

    virtual bool acceptsExtension(const std::string& extension) {
        return osgDB::equalCaseInsensitive(extension,"x") ? true : false;
    }

    virtual ReadResult readNode(const std::string& fileName,
                                const osgDB::ReaderWriter::Options* options);

private:
    osg::Geode* convertFromDX(DX::Object& obj, bool flipTexture, float creaseAngle);
};

// Register with Registry to instantiate the above reader/writer.
osgDB::RegisterReaderWriterProxy<ReaderWriterDirectX> g_readerWriter_DirectX_Proxy;

// Read node
osgDB::ReaderWriter::ReadResult ReaderWriterDirectX::readNode(const std::string& fileName,
                                                              const osgDB::ReaderWriter::Options* options)
{
    std::string ext = osgDB::getLowerCaseFileExtension(fileName);
    if (!acceptsExtension(ext))
        return ReadResult::FILE_NOT_HANDLED;

    osg::notify(osg::INFO) << "ReaderWriterDirectX::readNode(" << fileName.c_str() << ")\n";

    // Load DirectX mesh
    DX::Object obj;
    if (obj.load(fileName.c_str())) {

        // Options?
        bool flipTexture = true;
        float creaseAngle = 80.0f;
        if (options) {
            const std::string option = options->getOptionString();
            if (option.find("flipTexture") != std::string::npos)
                flipTexture = false;
            if (option.find("creaseAngle") != std::string::npos) {
                // TODO
            }
        }

        // Convert to osg::Geode
        osg::Geode* geode = convertFromDX(obj, flipTexture, creaseAngle);
        if (!geode)
            return ReadResult::FILE_NOT_HANDLED;

        return geode;
    }

    return ReadResult::FILE_NOT_HANDLED;
}

// Convert DirectX mesh to osg::Geode
osg::Geode* ReaderWriterDirectX::convertFromDX(DX::Object& obj,
                                               bool flipTexture, float creaseAngle)
{
    // Fetch mesh
    const DX::Mesh* mesh = obj.getMesh();
    if (!mesh)
        return NULL;

    const DX::MeshMaterialList* meshMaterial = obj.getMeshMaterialList();
    if (!meshMaterial)
        return NULL;

    const DX::MeshNormals* meshNormals = obj.getMeshNormals();
    if (!meshNormals) {
        obj.generateNormals(creaseAngle);
        meshNormals = obj.getMeshNormals();
    }
    if (!meshNormals)
        return NULL;

    const DX::MeshTextureCoords* meshTexCoords = obj.getMeshTextureCoords();
    if (!meshTexCoords)
        return NULL;

    /*
     * - MeshMaterialList contains a list of Material and a per-face
     *   information with Material is to be applied to which face.
     * - Mesh contains a list of Vertices and a per-face information
     *   which vertices (three or four) belong to this face.
     * - MeshNormals contains a list of Normals and a per-face information
     *   which normal is used by which vertex.
     * - MeshTextureCoords contains a list of per-vertex texture coordinates.
     *
     * - Uses left-hand CS with Y-up, Z-into
     *   obj_x -> osg_x
     *   obj_y -> osg_z
     *   obj_z -> osg_y
     *
     * - Polys are CW oriented
     */
	std::vector<osg::Geometry*> geomList;

    unsigned int i;
    for (i = 0; i < meshMaterial->material.size(); i++) {

        const DX::Material& mtl = meshMaterial->material[i];
        osg::StateSet* state = new osg::StateSet;

        // Material
        osg::Material* material = new osg::Material;
        state->setAttributeAndModes(material);

        float alpha = mtl.faceColor.alpha;
        osg::Vec4 ambient(mtl.faceColor.red,
                          mtl.faceColor.green,
                          mtl.faceColor.blue,
                          alpha);
        material->setAmbient(osg::Material::FRONT, ambient);
        material->setDiffuse(osg::Material::FRONT, ambient);

        material->setShininess(osg::Material::FRONT, mtl.power);

        osg::Vec4 specular(mtl.specularColor.red,
                           mtl.specularColor.green,
                           mtl.specularColor.blue, alpha);
        material->setSpecular(osg::Material::FRONT, specular);

        osg::Vec4 emissive(mtl.emissiveColor.red,
                           mtl.emissiveColor.green,
                           mtl.emissiveColor.blue, alpha);
        material->setEmission(osg::Material::FRONT, emissive);

        // Transparency? Set render hint & blending
        if (alpha < 1.0f) {
            state->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
            state->setMode(GL_BLEND, osg::StateAttribute::ON);
        }
        else
            state->setMode(GL_BLEND, osg::StateAttribute::OFF);

        unsigned int textureCount = mtl.texture.size();
        for (unsigned int j = 0; j < textureCount; j++) {
            // Load image
            osg::Image* image = osgDB::readImageFile(mtl.texture[j]);
            if (!image)
                continue;

            // Texture
            osg::Texture2D* texture = new osg::Texture2D;
            texture->setImage(image);
            texture->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::REPEAT);
            texture->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::REPEAT);
            state->setTextureAttributeAndModes(j, texture);
        }

        // Geometry
        osg::Geometry* geom = new osg::Geometry;
        geomList.push_back(geom);

        geom->setStateSet(state);

        // Arrays to hold vertices, normals, and texcoords.
        geom->setVertexArray(new osg::Vec3Array);
        geom->setNormalArray(new osg::Vec3Array);
        geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
        if (textureCount) {
            // All texture units share the same array
            osg::Vec2Array* texCoords = new osg::Vec2Array;
            for (unsigned int j = 0; j < textureCount; j++)
                geom->setTexCoordArray(j, texCoords);
        }

        geom->addPrimitiveSet(new osg::DrawArrayLengths(osg::PrimitiveSet::POLYGON));
    }

    assert(mesh->faces.size() == meshMaterial->faceIndices.size());

    // Add faces to Geometry
    for (i = 0; i < meshMaterial->faceIndices.size(); i++) {

        // Geometry for Material
        unsigned int mi = meshMaterial->faceIndices[i];
        osg::Geometry* geom = geomList[mi];

        // #pts of this face
        unsigned int np = mesh->faces[i].size();
        ((osg::DrawArrayLengths*) geom->getPrimitiveSet(0))->push_back(np);

        assert(np == meshNormals->faceNormals[i].size());

        osg::Vec3Array* vertexArray = (osg::Vec3Array*) geom->getVertexArray();
        osg::Vec3Array* normalArray = (osg::Vec3Array*) geom->getNormalArray();
        osg::Vec2Array* texCoordArray = (osg::Vec2Array*) geom->getTexCoordArray(0);

        // Add vertices, normals, texcoords
        for (unsigned int j = 0; j < np; j++) {

            // Convert CW to CCW order
            unsigned int jj = (j > 0 ? np - j : j);

            // Vertices
            unsigned int vi = mesh->faces[i][jj];
            if (vertexArray) {
                // Transform Xleft/Yup/Zinto to Xleft/Yinto/Zup
                const DX::Vector& v = mesh->vertices[vi];
                vertexArray->push_back(osg::Vec3(v.x,v.z,v.y));
            }

            // Normals
            unsigned int ni = meshNormals->faceNormals[i][jj];
            if (normalArray) {
                // Transform Xleft/Yup/Zinto to Xleft/Yinto/Zup
                const DX::Vector& n = meshNormals->normals[ni];
                normalArray->push_back(osg::Vec3(n.x,n.z,n.y));
            }

            // TexCoords
            if (texCoordArray) {
                const DX::Coords2d& tc = (*meshTexCoords)[vi];
                osg::Vec2 uv;
                if (flipTexture)
                    uv.set(tc.u, 1.0f - tc.v); // Image is upside down
                else
                    uv.set(tc.u, tc.v);
                texCoordArray->push_back(uv);
            }
        }
    }

    // Add non-empty nodes to Geode
    osg::Geode* geode = new osg::Geode;
    for (i = 0; i < geomList.size(); i++) {
        osg::Geometry* geom = geomList[i];
        if (((osg::Vec3Array*) geom->getVertexArray())->size())
            geode->addDrawable(geom);
    }

    // Back-face culling
    osg::StateSet* state = new osg::StateSet;
    geode->setStateSet(state);

    osg::CullFace* cullFace = new osg::CullFace;
    cullFace->setMode(osg::CullFace::BACK);
    state->setAttributeAndModes(cullFace);

    return geode;
}
<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License 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. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/inc_navier_stokes_spgsm_stab.h"

// GRINS
#include "grins/assembly_context.h"

//libMesh
#include "libmesh/quadrature.h"

namespace GRINS
{

  IncompressibleNavierStokesSPGSMStabilization::IncompressibleNavierStokesSPGSMStabilization( const std::string& physics_name,
                                                                                const GetPot& input )
    : IncompressibleNavierStokesStabilizationBase(physics_name,input)
  {
    this->read_input_options(input);

    return;
  }

  IncompressibleNavierStokesSPGSMStabilization::~IncompressibleNavierStokesSPGSMStabilization()
  {
    return;
  }

  void IncompressibleNavierStokesSPGSMStabilization::element_time_derivative( bool compute_jacobian,
                                                                              AssemblyContext& context,
                                                                              CachedValues& /*cache*/ )
  {
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("IncompressibleNavierStokesSPGSMStabilization::element_time_derivative");
#endif

    // The number of local degrees of freedom in each variable.
    const unsigned int n_p_dofs = context.get_dof_indices(this->_p_var).size();
    const unsigned int n_u_dofs = context.get_dof_indices(this->_u_var).size();

    // Check number of dofs is same for _u_var, v_var and w_var.
    libmesh_assert (n_u_dofs == context.get_dof_indices(this->_v_var).size());
    if (this->_dim == 3)
      {
        libmesh_assert (n_u_dofs == context.get_dof_indices(this->_w_var).size());
      }

    // Element Jacobian * quadrature weights for interior integration.
    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(this->_u_var)->get_JxW();

    // The pressure shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& p_dphi =
      context.get_element_fe(this->_p_var)->get_dphi();

    // The velocity shape function gradients at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
      context.get_element_fe(this->_u_var)->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_u_var); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_v_var); // R_{v}
    libMesh::DenseSubVector<libMesh::Number> *Fw = NULL;
    if(this->_dim == 3)
      {
        Fw = &context.get_elem_residual(this->_w_var); // R_{w}
      }

    libMesh::DenseSubVector<libMesh::Number> &Fp = context.get_elem_residual(this->_p_var); // R_{p}

    libMesh::FEBase* fe = context.get_element_fe(this->_u_var);

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::RealGradient g = this->_stab_helper.compute_g( fe, context, qp );
        libMesh::RealTensor G = this->_stab_helper.compute_G( fe, context, qp );

        libMesh::RealGradient U( context.interior_value( this->_u_var, qp ),
                                 context.interior_value( this->_v_var, qp ) );
        if( this->_dim == 3 )
          {
            U(2) = context.interior_value( this->_w_var, qp );
          }

        libMesh::Real tau_M = this->_stab_helper.compute_tau_momentum( context, qp, g, G, this->_rho, U, this->_mu, this->_is_steady );
        libMesh::Real tau_C = this->_stab_helper.compute_tau_continuity( tau_M, g );

        libMesh::RealGradient RM_s = this->compute_res_momentum_steady( context, qp );
        libMesh::Real RC = this->compute_res_continuity( context, qp );

        for (unsigned int i=0; i != n_p_dofs; i++)
          {
            Fp(i) += tau_M*RM_s*p_dphi[i][qp]*JxW[qp];
          }

        for (unsigned int i=0; i != n_u_dofs; i++)
          {
            Fu(i) += ( - tau_C*RC*u_gradphi[i][qp](0)
                       - tau_M*RM_s(0)*_rho*U*u_gradphi[i][qp]  )*JxW[qp];

            Fv(i) += ( - tau_C*RC*u_gradphi[i][qp](1)
                       - tau_M*RM_s(1)*_rho*U*u_gradphi[i][qp] )*JxW[qp];

            if( this->_dim == 3 )
              {
                (*Fw)(i) += ( - tau_C*RC*u_gradphi[i][qp](2)
                              - tau_M*RM_s(2)*_rho*U*u_gradphi[i][qp] )*JxW[qp];
              }
          }

        if( compute_jacobian )
          {
            libmesh_not_implemented();
          }

      }

#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("IncompressibleNavierStokesSPGSMStabilization::element_time_derivative");
#endif

    return;
  }

  void IncompressibleNavierStokesSPGSMStabilization::mass_residual( bool compute_jacobian,
                                                                    AssemblyContext& context,
                                                                    CachedValues& /*cache*/ )
  {
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("IncompressibleNavierStokesSPGSMStabilization::mass_residual");
#endif

    // The number of local degrees of freedom in each variable.
    const unsigned int n_p_dofs = context.get_dof_indices(this->_p_var).size();
    const unsigned int n_u_dofs = context.get_dof_indices(this->_u_var).size();

    // Element Jacobian * quadrature weights for interior integration.
    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(this->_u_var)->get_JxW();

    // The pressure shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& p_dphi =
      context.get_element_fe(this->_p_var)->get_dphi();

    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
      context.get_element_fe(this->_u_var)->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_u_var); // R_{p}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_v_var); // R_{p}
    libMesh::DenseSubVector<libMesh::Number> *Fw = NULL;
    if(this->_dim == 3)
      Fw = &context.get_elem_residual(this->_w_var); // R_{w}

    libMesh::DenseSubVector<libMesh::Number> &Fp = context.get_elem_residual(this->_p_var); // R_{p}

    libMesh::FEBase* fe = context.get_element_fe(this->_u_var);

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::RealGradient g = this->_stab_helper.compute_g( fe, context, qp );
        libMesh::RealTensor G = this->_stab_helper.compute_G( fe, context, qp );

        libMesh::RealGradient U( context.fixed_interior_value( this->_u_var, qp ),
                                 context.fixed_interior_value( this->_v_var, qp ) );
        if( this->_dim == 3 )
          {
            U(2) = context.fixed_interior_value( this->_w_var, qp );
          }

        libMesh::Real tau_M = this->_stab_helper.compute_tau_momentum( context, qp, g, G, this->_rho, U, this->_mu, false );

        libMesh::RealGradient RM_t = this->compute_res_momentum_transient( context, qp );

        for (unsigned int i=0; i != n_p_dofs; i++)
          {
            Fp(i) += tau_M*RM_t*p_dphi[i][qp]*JxW[qp];
          }

        for (unsigned int i=0; i != n_u_dofs; i++)
          {
            Fu(i) += -tau_M*RM_t(0)*_rho*U*u_gradphi[i][qp]*JxW[qp];

            Fv(i) += -tau_M*RM_t(1)*_rho*U*u_gradphi[i][qp]*JxW[qp];

            if( this->_dim == 3 )
              {
                (*Fw)(i) += -tau_M*RM_t(2)*_rho*U*u_gradphi[i][qp]*JxW[qp];
              }
          }

        if( compute_jacobian )
          {
            libmesh_not_implemented();
          }

      }

#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("IncompressibleNavierStokesSPGSMStabilization::mass_residual");
#endif

    return;
  }

} // end namespace GRINS
<commit_msg>Have incompressible Navier-Stokes SPGSM stabilization use updated helper.<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2010-2013 The PECOS Development Team
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the Version 2.1 GNU Lesser General
// Public License 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. 51 Franklin Street, Fifth Floor,
// Boston, MA  02110-1301  USA
//
//-----------------------------------------------------------------------el-

// This class
#include "grins/inc_navier_stokes_spgsm_stab.h"

// GRINS
#include "grins/assembly_context.h"

//libMesh
#include "libmesh/quadrature.h"

namespace GRINS
{

  IncompressibleNavierStokesSPGSMStabilization::IncompressibleNavierStokesSPGSMStabilization( const std::string& physics_name,
                                                                                const GetPot& input )
    : IncompressibleNavierStokesStabilizationBase(physics_name,input)
  {
    this->read_input_options(input);

    return;
  }

  IncompressibleNavierStokesSPGSMStabilization::~IncompressibleNavierStokesSPGSMStabilization()
  {
    return;
  }

  void IncompressibleNavierStokesSPGSMStabilization::element_time_derivative( bool compute_jacobian,
                                                                              AssemblyContext& context,
                                                                              CachedValues& /*cache*/ )
  {
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("IncompressibleNavierStokesSPGSMStabilization::element_time_derivative");
#endif

    // The number of local degrees of freedom in each variable.
    const unsigned int n_p_dofs = context.get_dof_indices(this->_flow_vars.p_var()).size();
    const unsigned int n_u_dofs = context.get_dof_indices(this->_flow_vars.u_var()).size();

    // Check number of dofs is same for _flow_vars.u_var(), v_var and w_var.
    libmesh_assert (n_u_dofs == context.get_dof_indices(this->_flow_vars.v_var()).size());
    if (this->_dim == 3)
      {
        libmesh_assert (n_u_dofs == context.get_dof_indices(this->_flow_vars.w_var()).size());
      }

    // Element Jacobian * quadrature weights for interior integration.
    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(this->_flow_vars.u_var())->get_JxW();

    // The pressure shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& p_dphi =
      context.get_element_fe(this->_flow_vars.p_var())->get_dphi();

    // The velocity shape function gradients at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
      context.get_element_fe(this->_flow_vars.u_var())->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_flow_vars.u_var()); // R_{u}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_flow_vars.v_var()); // R_{v}
    libMesh::DenseSubVector<libMesh::Number> *Fw = NULL;
    if(this->_dim == 3)
      {
        Fw = &context.get_elem_residual(this->_flow_vars.w_var()); // R_{w}
      }

    libMesh::DenseSubVector<libMesh::Number> &Fp = context.get_elem_residual(this->_flow_vars.p_var()); // R_{p}

    libMesh::FEBase* fe = context.get_element_fe(this->_flow_vars.u_var());

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::RealGradient g = this->_stab_helper.compute_g( fe, context, qp );
        libMesh::RealTensor G = this->_stab_helper.compute_G( fe, context, qp );

        libMesh::RealGradient U( context.interior_value( this->_flow_vars.u_var(), qp ),
                                 context.interior_value( this->_flow_vars.v_var(), qp ) );
        if( this->_dim == 3 )
          {
            U(2) = context.interior_value( this->_flow_vars.w_var(), qp );
          }

        libMesh::Real tau_M = this->_stab_helper.compute_tau_momentum( context, qp, g, G, this->_rho, U, this->_mu, this->_is_steady );
        libMesh::Real tau_C = this->_stab_helper.compute_tau_continuity( tau_M, g );

        libMesh::RealGradient RM_s = this->_stab_helper.compute_res_momentum_steady( context, qp, _rho, _mu );
        libMesh::Real RC = this->_stab_helper.compute_res_continuity( context, qp );

        for (unsigned int i=0; i != n_p_dofs; i++)
          {
            Fp(i) += tau_M*RM_s*p_dphi[i][qp]*JxW[qp];
          }

        for (unsigned int i=0; i != n_u_dofs; i++)
          {
            Fu(i) += ( - tau_C*RC*u_gradphi[i][qp](0)
                       - tau_M*RM_s(0)*_rho*U*u_gradphi[i][qp]  )*JxW[qp];

            Fv(i) += ( - tau_C*RC*u_gradphi[i][qp](1)
                       - tau_M*RM_s(1)*_rho*U*u_gradphi[i][qp] )*JxW[qp];

            if( this->_dim == 3 )
              {
                (*Fw)(i) += ( - tau_C*RC*u_gradphi[i][qp](2)
                              - tau_M*RM_s(2)*_rho*U*u_gradphi[i][qp] )*JxW[qp];
              }
          }

        if( compute_jacobian )
          {
            libmesh_not_implemented();
          }

      }

#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("IncompressibleNavierStokesSPGSMStabilization::element_time_derivative");
#endif

    return;
  }

  void IncompressibleNavierStokesSPGSMStabilization::mass_residual( bool compute_jacobian,
                                                                    AssemblyContext& context,
                                                                    CachedValues& /*cache*/ )
  {
#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->BeginTimer("IncompressibleNavierStokesSPGSMStabilization::mass_residual");
#endif

    // The number of local degrees of freedom in each variable.
    const unsigned int n_p_dofs = context.get_dof_indices(this->_flow_vars.p_var()).size();
    const unsigned int n_u_dofs = context.get_dof_indices(this->_flow_vars.u_var()).size();

    // Element Jacobian * quadrature weights for interior integration.
    const std::vector<libMesh::Real> &JxW =
      context.get_element_fe(this->_flow_vars.u_var())->get_JxW();

    // The pressure shape functions at interior quadrature points.
    const std::vector<std::vector<libMesh::RealGradient> >& p_dphi =
      context.get_element_fe(this->_flow_vars.p_var())->get_dphi();

    const std::vector<std::vector<libMesh::RealGradient> >& u_gradphi =
      context.get_element_fe(this->_flow_vars.u_var())->get_dphi();

    libMesh::DenseSubVector<libMesh::Number> &Fu = context.get_elem_residual(this->_flow_vars.u_var()); // R_{p}
    libMesh::DenseSubVector<libMesh::Number> &Fv = context.get_elem_residual(this->_flow_vars.v_var()); // R_{p}
    libMesh::DenseSubVector<libMesh::Number> *Fw = NULL;
    if(this->_dim == 3)
      Fw = &context.get_elem_residual(this->_flow_vars.w_var()); // R_{w}

    libMesh::DenseSubVector<libMesh::Number> &Fp = context.get_elem_residual(this->_flow_vars.p_var()); // R_{p}

    libMesh::FEBase* fe = context.get_element_fe(this->_flow_vars.u_var());

    unsigned int n_qpoints = context.get_element_qrule().n_points();

    for (unsigned int qp=0; qp != n_qpoints; qp++)
      {
        libMesh::RealGradient g = this->_stab_helper.compute_g( fe, context, qp );
        libMesh::RealTensor G = this->_stab_helper.compute_G( fe, context, qp );

        libMesh::RealGradient U( context.fixed_interior_value( this->_flow_vars.u_var(), qp ),
                                 context.fixed_interior_value( this->_flow_vars.v_var(), qp ) );
        if( this->_dim == 3 )
          {
            U(2) = context.fixed_interior_value( this->_flow_vars.w_var(), qp );
          }

        libMesh::Real tau_M = this->_stab_helper.compute_tau_momentum( context, qp, g, G, this->_rho, U, this->_mu, false );

        libMesh::RealGradient RM_t = this->_stab_helper.compute_res_momentum_transient( context, qp, _rho );

        for (unsigned int i=0; i != n_p_dofs; i++)
          {
            Fp(i) += tau_M*RM_t*p_dphi[i][qp]*JxW[qp];
          }

        for (unsigned int i=0; i != n_u_dofs; i++)
          {
            Fu(i) += -tau_M*RM_t(0)*_rho*U*u_gradphi[i][qp]*JxW[qp];

            Fv(i) += -tau_M*RM_t(1)*_rho*U*u_gradphi[i][qp]*JxW[qp];

            if( this->_dim == 3 )
              {
                (*Fw)(i) += -tau_M*RM_t(2)*_rho*U*u_gradphi[i][qp]*JxW[qp];
              }
          }

        if( compute_jacobian )
          {
            libmesh_not_implemented();
          }

      }

#ifdef GRINS_USE_GRVY_TIMERS
    this->_timer->EndTimer("IncompressibleNavierStokesSPGSMStabilization::mass_residual");
#endif

    return;
  }

} // end namespace GRINS
<|endoftext|>


<commit_before>#pragma once

#include "../../../../include/cpp/ListNode.hxx"

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
  ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    ListNode* solution = new ListNode(0);

    return solution;
  }
};
<commit_msg>addtwonumbers solution<commit_after>#pragma once

#include "../../../../include/cpp/ListNode.hxx"

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
  ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    ListNode* solution = new ListNode{0};
    ListNode* curr = solution;

    ListNode* linkA = l1, * linkB = l2;

    int sum;
    bool isGreater10{false};
    for (; linkA != nullptr && linkB != nullptr; (linkA = linkA->next), linkB = linkB->next) {
      sum = linkA->val + linkB->val;

      if (isGreater10) {
        ++sum;
      }

      isGreater10 = sum > 9;

      if (isGreater10) {
        sum -= 10;
      }

      curr->val = sum;

      if (linkA->next != nullptr) {
        curr->next = new ListNode{1};
        curr = curr->next;
      }
    }

    if (isGreater10) {
      curr->next = new ListNode{1};
    }

    return solution;
  }
};
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "settingslayer_symbian_p.h"
#include <QVariant>
#include "xqsettingskey_p.h"
#include "xqpublishandsubscribeutils.h"

#ifdef __WINS__
    #include "pathmapper_symbian.cpp"
    #include "qcrmlparser.cpp"
#else
    #include "pathmapper_proxy_symbian.cpp"
#endif

#include <QDebug>

QTM_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(SymbianSettingsLayer, symbianSettingsLayer);
QVALUESPACE_AUTO_INSTALL_LAYER(SymbianSettingsLayer);

SymbianSettingsLayer::SymbianSettingsLayer()
{
    connect(&m_settingsManager, SIGNAL(valueChanged(const XQSettingsKey&, const QVariant&)),
            this, SLOT(notifyChange(const XQSettingsKey&)));
    connect(&m_settingsManager, SIGNAL(itemDeleted(const XQSettingsKey&)),
            this, SLOT(notifyChange(const XQSettingsKey&)));
}

SymbianSettingsLayer::~SymbianSettingsLayer()
{
    QMutableHashIterator<QString, SymbianSettingsHandle *> i(m_handles);
    while (i.hasNext()) {
        i.next();

        removeHandle(Handle(i.value()));
    }
}

QString SymbianSettingsLayer::name()
{
    return QLatin1String("Symbian Settings Layer");
}

QUuid SymbianSettingsLayer::id()
{
    return QVALUESPACE_SYMBIAN_SETTINGS_LAYER;
}

unsigned int SymbianSettingsLayer::order()
{
    return 0;
}

QValueSpace::LayerOptions SymbianSettingsLayer::layerOptions() const
{
    return QValueSpace::PermanentLayer |
        QValueSpace::WritableLayer;
}

SymbianSettingsLayer *SymbianSettingsLayer::instance()
{
    return symbianSettingsLayer();
}

bool SymbianSettingsLayer::startup(Type type)
{
    return true;
}

bool SymbianSettingsLayer::value(Handle handle, QVariant *data)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return false;

    return value(InvalidHandle, sh->path, data);
}

bool SymbianSettingsLayer::value(Handle handle, const QString &subPath, QVariant *data)
{
    if (handle != InvalidHandle && !symbianSettingsHandle(handle))
        return false;

    QString path(subPath);
    while (path.endsWith(QLatin1Char('/')))
        path.chop(1);
    if (handle != InvalidHandle)
        while (path.startsWith(QLatin1Char('/')))
            path = path.mid(1);
    int index = path.lastIndexOf(QLatin1Char('/'), -1);

    bool createdHandle = false;

    QString value;
    if (index == -1) {
        value = path;
    } else {
        // want a value that is in a sub path under handle
        value = path.mid(index + 1);
        path.truncate(index);

        handle = item(handle, path);
        createdHandle = true;
    }

    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return false;

    QString fullPath(sh->path);
    if (fullPath != QLatin1String("/"))
        fullPath.append(QLatin1Char('/'));

    fullPath.append(value);

    bool success = false;
    PathMapper::Target target;
    quint32 category;
    quint32 key;
    if (m_pathMapper.resolvePath(fullPath, target, category, key)) {
        XQSettingsKey settingsKey(XQSettingsKey::Target(target), (long)category, (unsigned long)key);
        QVariant readValue = m_settingsManager.readItemValue(settingsKey);
        if (readValue.type() == QVariant::ByteArray) {
            QDataStream readStream(readValue.toByteArray());
            QVariant serializedValue;
            readStream >> serializedValue;
            if (serializedValue.isValid()) {
                *data = serializedValue;
            } else {
                *data = readValue;
            }
            success = true;
        } else {
            *data = readValue;
            success = data->isValid();
        }
    }

    if (createdHandle)
        removeHandle(handle);

    return success;
}

QSet<QString> SymbianSettingsLayer::children(Handle handle)
{
    QSet<QString> foundChildren;

    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return foundChildren;

    m_pathMapper.getChildren(sh->path, foundChildren);
    return foundChildren;
}

QAbstractValueSpaceLayer::Handle SymbianSettingsLayer::item(Handle parent, const QString &path)
{
    QString fullPath;

    // Fail on invalid path.
    if (path.isEmpty() || path.contains(QLatin1String("//")))
        return InvalidHandle;

    if (parent == InvalidHandle) {
        fullPath = path;
    } else {
        SymbianSettingsHandle *sh = symbianSettingsHandle(parent);
        if (!sh)
            return InvalidHandle;

        if (path == QLatin1String("/")) {
            fullPath = sh->path;
        } else if (sh->path.endsWith(QLatin1Char('/')) && path.startsWith(QLatin1Char('/')))
            fullPath = sh->path + path.mid(1);
        else if (!sh->path.endsWith(QLatin1Char('/')) && !path.startsWith(QLatin1Char('/')))
            fullPath = sh->path + QLatin1Char('/') + path;
        else
            fullPath = sh->path + path;
    }

    if (m_handles.contains(fullPath)) {
        SymbianSettingsHandle *sh = m_handles.value(fullPath);
        ++sh->refCount;
        return Handle(sh);
    }

    // Create a new handle for path
    SymbianSettingsHandle *sh = new SymbianSettingsHandle(fullPath);
    m_handles.insert(fullPath, sh);

    return Handle(sh);
}

void SymbianSettingsLayer::setProperty(Handle handle, Properties properties)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return;

    foreach (const QString &fullPath, m_pathMapper.childPaths(sh->path)) {
        PathMapper::Target target;
        quint32 category;
        quint32 key;
        if (m_pathMapper.resolvePath(fullPath, target, category, key)) {
            XQSettingsKey settingsKey(XQSettingsKey::Target(target), (long)category, (unsigned long)key);
            QByteArray hash;
            hash += qHash(target);
            hash += qHash((long)category);
            hash += qHash((unsigned long)key);

            if (properties & QAbstractValueSpaceLayer::Publish) {
                m_settingsManager.startMonitoring(settingsKey);
                m_monitoringHandles[hash] = sh;
                m_monitoringPaths.insert(fullPath);
            } else {
                m_settingsManager.stopMonitoring(settingsKey);
                m_monitoringHandles.remove(hash);
                m_monitoringPaths.remove(fullPath);
            }
        }
    }
}

void SymbianSettingsLayer::removeHandle(Handle handle)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return;

    if (--sh->refCount)
        return;

    m_handles.remove(sh->path);

    delete sh;
}

bool SymbianSettingsLayer::setValue(QValueSpacePublisher *creator,
                                    Handle handle,
                                    const QString &subPath,
                                    const QVariant &data)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return false;

    QString path(subPath);
    while (path.endsWith(QLatin1Char('/')))
        path.chop(1);

    int index = path.lastIndexOf(QLatin1Char('/'), -1);

    bool createdHandle = false;

    QString value;
    if (index == -1) {
        value = path;
    } else {
        // want a value that is in a sub path under handle
        value = path.mid(index + 1);
        path.truncate(index);

        if (path.isEmpty())
            path.append(QLatin1Char('/'));

        sh = symbianSettingsHandle(item(Handle(sh), path));
        createdHandle = true;
    }

    QString fullPath(sh->path);
    if (fullPath != QLatin1String("/"))
        fullPath.append(QLatin1Char('/'));

    fullPath.append(value);

    bool success = false;
    PathMapper::Target target;
    quint32 category;
    quint32 key;
    if (m_pathMapper.resolvePath(fullPath, target, category, key)) {
        if (target == PathMapper::TargetRPropery) {
            XQPublishAndSubscribeUtils utils(m_settingsManager);

            XQSettingsManager::Type type = XQSettingsManager::TypeVariant;
            if (data.type() == QVariant::Int) {
                type = XQSettingsManager::TypeInt;
            } else {
                type = XQSettingsManager::TypeByteArray;
            }
            utils.defineProperty(
                XQPublishAndSubscribeSettingsKey((long)category, (unsigned long)key), type);
        }

        XQSettingsKey settingsKey(XQSettingsKey::Target(target), (long)category, (unsigned long)key);

        if (m_monitoringPaths.contains(fullPath)) {
            m_settingsManager.startMonitoring(settingsKey);
        }

        if (data.type() == QVariant::Int || data.type() == QVariant::ByteArray) {
            //Write integers and bytearrays as such
            success = m_settingsManager.writeItemValue(settingsKey, data);
        } else {
            //Write other data types serialized into a bytearray
            QByteArray byteArray;
            QDataStream writeStream(&byteArray, QIODevice::WriteOnly);
            writeStream << data;
            success = m_settingsManager.writeItemValue(settingsKey, QVariant(byteArray));
        }
    }

    if (createdHandle)
        removeHandle(Handle(sh));
    return success;
}

void SymbianSettingsLayer::sync()
{
    //Not needed
}

bool SymbianSettingsLayer::removeSubTree(QValueSpacePublisher * /*creator*/, Handle /*handle*/)
{
    //Not needed
    return false;
}

bool SymbianSettingsLayer::removeValue(QValueSpacePublisher *creator,
    Handle handle,
    const QString &subPath)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return false;

    QString path(subPath);
    while (path.endsWith(QLatin1Char('/')))
        path.chop(1);

    int index = path.lastIndexOf(QLatin1Char('/'), -1);

    bool createdHandle = false;

    QString value;
    if (index == -1) {
        value = path;
    } else {
        // want a value that is in a sub path under handle
        value = path.mid(index + 1);
        path.truncate(index);

        if (path.isEmpty())
            path.append(QLatin1Char('/'));

        sh = symbianSettingsHandle(item(Handle(sh), path));
        createdHandle = true;
    }

    QString fullPath(sh->path);
    if (fullPath != QLatin1String("/"))
        fullPath.append(QLatin1Char('/'));

    fullPath.append(value);

    bool success = false;
    PathMapper::Target target;
    quint32 category;
    quint32 key;
    if (m_pathMapper.resolvePath(fullPath, target, category, key)) {
        if (target == PathMapper::TargetRPropery) {
            XQPublishAndSubscribeUtils utils(m_settingsManager);
            utils.deleteProperty(XQPublishAndSubscribeSettingsKey((long)category, (unsigned long)key));
        }
    }

    if (createdHandle)
        removeHandle(Handle(sh));

    return success;
}

void SymbianSettingsLayer::addWatch(QValueSpacePublisher *, Handle)
{
    //Not needed
}

void SymbianSettingsLayer::removeWatches(QValueSpacePublisher *, Handle)
{
    //Not needed
}

bool SymbianSettingsLayer::supportsInterestNotification() const
{
    return false;
}

bool SymbianSettingsLayer::notifyInterest(Handle, bool)
{
    //Not needed
    return false;
}

void SymbianSettingsLayer::notifyChange(const XQSettingsKey& key)
{
    QByteArray hash;
    hash += qHash(key.target());
    hash += qHash(key.uid());
    hash += qHash(key.key());

    if (m_monitoringHandles.contains(hash)) {
        emit handleChanged(Handle(m_monitoringHandles.value(hash)));
    }
}

#include "moc_settingslayer_symbian_p.cpp"

QTM_END_NAMESPACE
<commit_msg>coverity fix for MOBILITY-1742<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "settingslayer_symbian_p.h"
#include <QVariant>
#include "xqsettingskey_p.h"
#include "xqpublishandsubscribeutils.h"

#ifdef __WINS__
    #include "pathmapper_symbian.cpp"
    #include "qcrmlparser.cpp"
#else
    #include "pathmapper_proxy_symbian.cpp"
#endif

#include <QDebug>

QTM_BEGIN_NAMESPACE

Q_GLOBAL_STATIC(SymbianSettingsLayer, symbianSettingsLayer);
QVALUESPACE_AUTO_INSTALL_LAYER(SymbianSettingsLayer);

SymbianSettingsLayer::SymbianSettingsLayer()
{
    connect(&m_settingsManager, SIGNAL(valueChanged(const XQSettingsKey&, const QVariant&)),
            this, SLOT(notifyChange(const XQSettingsKey&)));
    connect(&m_settingsManager, SIGNAL(itemDeleted(const XQSettingsKey&)),
            this, SLOT(notifyChange(const XQSettingsKey&)));
}

SymbianSettingsLayer::~SymbianSettingsLayer()
{
    QMutableHashIterator<QString, SymbianSettingsHandle *> i(m_handles);
    while (i.hasNext()) {
        i.next();

        removeHandle(Handle(i.value()));
    }
}

QString SymbianSettingsLayer::name()
{
    return QLatin1String("Symbian Settings Layer");
}

QUuid SymbianSettingsLayer::id()
{
    return QVALUESPACE_SYMBIAN_SETTINGS_LAYER;
}

unsigned int SymbianSettingsLayer::order()
{
    return 0;
}

QValueSpace::LayerOptions SymbianSettingsLayer::layerOptions() const
{
    return QValueSpace::PermanentLayer |
        QValueSpace::WritableLayer;
}

SymbianSettingsLayer *SymbianSettingsLayer::instance()
{
    return symbianSettingsLayer();
}

bool SymbianSettingsLayer::startup(Type type)
{
    return true;
}

bool SymbianSettingsLayer::value(Handle handle, QVariant *data)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return false;

    return value(InvalidHandle, sh->path, data);
}

bool SymbianSettingsLayer::value(Handle handle, const QString &subPath, QVariant *data)
{
    if (handle != InvalidHandle && !symbianSettingsHandle(handle))
        return false;

    QString path(subPath);
    while (path.endsWith(QLatin1Char('/')))
        path.chop(1);
    if (handle != InvalidHandle)
        while (path.startsWith(QLatin1Char('/')))
            path = path.mid(1);
    int index = path.lastIndexOf(QLatin1Char('/'), -1);

    bool createdHandle = false;

    QString value;
    if (index == -1) {
        value = path;
    } else {
        // want a value that is in a sub path under handle
        value = path.mid(index + 1);
        path.truncate(index);

        handle = item(handle, path);
        createdHandle = true;
    }

    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return false;

    QString fullPath(sh->path);
    if (fullPath != QLatin1String("/"))
        fullPath.append(QLatin1Char('/'));

    fullPath.append(value);

    bool success = false;
    PathMapper::Target target;
    quint32 category;
    quint32 key;
    if (m_pathMapper.resolvePath(fullPath, target, category, key)) {
        XQSettingsKey settingsKey(XQSettingsKey::Target(target), (long)category, (unsigned long)key);
        QVariant readValue = m_settingsManager.readItemValue(settingsKey);
        if (readValue.type() == QVariant::ByteArray) {
            QDataStream readStream(readValue.toByteArray());
            QVariant serializedValue;
            readStream >> serializedValue;
            if (serializedValue.isValid()) {
                *data = serializedValue;
            } else {
                *data = readValue;
            }
            success = true;
        } else {
            *data = readValue;
            success = data->isValid();
        }
    }

    if (createdHandle)
        removeHandle(handle);

    return success;
}

QSet<QString> SymbianSettingsLayer::children(Handle handle)
{
    QSet<QString> foundChildren;

    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return foundChildren;

    m_pathMapper.getChildren(sh->path, foundChildren);
    return foundChildren;
}

QAbstractValueSpaceLayer::Handle SymbianSettingsLayer::item(Handle parent, const QString &path)
{
    QString fullPath;

    // Fail on invalid path.
    if (path.isEmpty() || path.contains(QLatin1String("//")))
        return InvalidHandle;

    if (parent == InvalidHandle) {
        fullPath = path;
    } else {
        SymbianSettingsHandle *sh = symbianSettingsHandle(parent);
        if (!sh)
            return InvalidHandle;

        if (path == QLatin1String("/")) {
            fullPath = sh->path;
        } else if (sh->path.endsWith(QLatin1Char('/')) && path.startsWith(QLatin1Char('/')))
            fullPath = sh->path + path.mid(1);
        else if (!sh->path.endsWith(QLatin1Char('/')) && !path.startsWith(QLatin1Char('/')))
            fullPath = sh->path + QLatin1Char('/') + path;
        else
            fullPath = sh->path + path;
    }

    if (m_handles.contains(fullPath)) {
        SymbianSettingsHandle *sh = m_handles.value(fullPath);
        ++sh->refCount;
        return Handle(sh);
    }

    // Create a new handle for path
    SymbianSettingsHandle *sh = new SymbianSettingsHandle(fullPath);
    m_handles.insert(fullPath, sh);

    return Handle(sh);
}

void SymbianSettingsLayer::setProperty(Handle handle, Properties properties)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return;

    foreach (const QString &fullPath, m_pathMapper.childPaths(sh->path)) {
        PathMapper::Target target;
        quint32 category;
        quint32 key;
        if (m_pathMapper.resolvePath(fullPath, target, category, key)) {
            XQSettingsKey settingsKey(XQSettingsKey::Target(target), (long)category, (unsigned long)key);
            QByteArray hash;
            hash += qHash(target);
            hash += qHash((long)category);
            hash += qHash((unsigned long)key);

            if (properties & QAbstractValueSpaceLayer::Publish) {
                m_settingsManager.startMonitoring(settingsKey);
                m_monitoringHandles[hash] = sh;
                m_monitoringPaths.insert(fullPath);
            } else {
                m_settingsManager.stopMonitoring(settingsKey);
                m_monitoringHandles.remove(hash);
                m_monitoringPaths.remove(fullPath);
            }
        }
    }
}

void SymbianSettingsLayer::removeHandle(Handle handle)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return;

    if (--sh->refCount)
        return;

    m_handles.remove(sh->path);

    delete sh;
}

bool SymbianSettingsLayer::setValue(QValueSpacePublisher *creator,
                                    Handle handle,
                                    const QString &subPath,
                                    const QVariant &data)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return false;

    QString path(subPath);
    while (path.endsWith(QLatin1Char('/')))
        path.chop(1);

    int index = path.lastIndexOf(QLatin1Char('/'), -1);

    bool createdHandle = false;

    QString value;
    if (index == -1) {
        value = path;
    } else {
        // want a value that is in a sub path under handle
        value = path.mid(index + 1);
        path.truncate(index);

        if (path.isEmpty())
            path.append(QLatin1Char('/'));

        sh = symbianSettingsHandle(item(Handle(sh), path));
        createdHandle = true;
    }

    QString fullPath(sh->path);
    if (fullPath != QLatin1String("/"))
        fullPath.append(QLatin1Char('/'));

    fullPath.append(value);

    bool success = false;
    PathMapper::Target target;
    quint32 category;
    quint32 key;
    if (m_pathMapper.resolvePath(fullPath, target, category, key)) {
        if (target == PathMapper::TargetRPropery) {
            XQPublishAndSubscribeUtils utils(m_settingsManager);

            XQSettingsManager::Type type = XQSettingsManager::TypeVariant;
            if (data.type() == QVariant::Int) {
                type = XQSettingsManager::TypeInt;
            } else {
                type = XQSettingsManager::TypeByteArray;
            }
            utils.defineProperty(
                XQPublishAndSubscribeSettingsKey((long)category, (unsigned long)key), type);
        }

        XQSettingsKey settingsKey(XQSettingsKey::Target(target), (long)category, (unsigned long)key);

        if (m_monitoringPaths.contains(fullPath)) {
            m_settingsManager.startMonitoring(settingsKey);
        }

        if (data.type() == QVariant::Int || data.type() == QVariant::ByteArray) {
            //Write integers and bytearrays as such
            success = m_settingsManager.writeItemValue(settingsKey, data);
        } else {
            //Write other data types serialized into a bytearray
            QByteArray byteArray;
            QDataStream writeStream(&byteArray, QIODevice::WriteOnly);
            writeStream << data;
            success = m_settingsManager.writeItemValue(settingsKey, QVariant(byteArray));
        }
    }

    if (createdHandle)
        removeHandle(Handle(sh));
    return success;
}

void SymbianSettingsLayer::sync()
{
    //Not needed
}

bool SymbianSettingsLayer::removeSubTree(QValueSpacePublisher * /*creator*/, Handle /*handle*/)
{
    //Not needed
    return false;
}

bool SymbianSettingsLayer::removeValue(QValueSpacePublisher *creator,
    Handle handle,
    const QString &subPath)
{
    SymbianSettingsHandle *sh = symbianSettingsHandle(handle);
    if (!sh)
        return false;

    QString path(subPath);
    while (path.endsWith(QLatin1Char('/')))
        path.chop(1);

    int index = path.lastIndexOf(QLatin1Char('/'), -1);

    bool createdHandle = false;

    QString value;
    if (index == -1) {
        value = path;
    } else {
        // want a value that is in a sub path under handle
        value = path.mid(index + 1);
        path.truncate(index);

        if (path.isEmpty())
            path.append(QLatin1Char('/'));

        sh = symbianSettingsHandle(item(Handle(sh), path));
        if (!sh)
        	return false;
        createdHandle = true;
    }

    QString fullPath(sh->path);
    if (fullPath != QLatin1String("/"))
        fullPath.append(QLatin1Char('/'));

    fullPath.append(value);

    bool success = false;
    PathMapper::Target target;
    quint32 category;
    quint32 key;
    if (m_pathMapper.resolvePath(fullPath, target, category, key)) {
        if (target == PathMapper::TargetRPropery) {
            XQPublishAndSubscribeUtils utils(m_settingsManager);
            utils.deleteProperty(XQPublishAndSubscribeSettingsKey((long)category, (unsigned long)key));
        }
    }

    if (createdHandle)
        removeHandle(Handle(sh));

    return success;
}

void SymbianSettingsLayer::addWatch(QValueSpacePublisher *, Handle)
{
    //Not needed
}

void SymbianSettingsLayer::removeWatches(QValueSpacePublisher *, Handle)
{
    //Not needed
}

bool SymbianSettingsLayer::supportsInterestNotification() const
{
    return false;
}

bool SymbianSettingsLayer::notifyInterest(Handle, bool)
{
    //Not needed
    return false;
}

void SymbianSettingsLayer::notifyChange(const XQSettingsKey& key)
{
    QByteArray hash;
    hash += qHash(key.target());
    hash += qHash(key.uid());
    hash += qHash(key.key());

    if (m_monitoringHandles.contains(hash)) {
        emit handleChanged(Handle(m_monitoringHandles.value(hash)));
    }
}

#include "moc_settingslayer_symbian_p.cpp"

QTM_END_NAMESPACE
<|endoftext|>