<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    "../../Streams/iostream/BinaryOutputStreamFromOStreamAdapter.h"
#include    "../../Streams/TextOutputStreamBinaryAdapter.h"

#include    "Writer.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::DataExchangeFormat;
using   namespace   Stroika::Foundation::Streams;

/*
 * TODO:
 *      No known issues
 */

/*
 ********************************************************************************
 *************** DataExchangeFormat::JSON::PrettyPrint **************************
 ********************************************************************************
 */
namespace   {
    void    Indent_ (const TextOutputStream& out, int indentLevel)
    {
        for (int i = 0; i < indentLevel; ++i) {
            out.Write (L"    ");
        }
    }
}
namespace   {
    void    PrettyPrint_ (const Memory::VariantValue& v, const TextOutputStream& out, int indentLevel);
    void    PrettyPrint_Null_ (const TextOutputStream& out)
    {
        out.Write (L"null");
    }
    void    PrettyPrint_ (bool v, const TextOutputStream& out)
    {
        if (v) {
            out.Write (L"true");
        }
        else {
            out.Write (L"false");
        }
    }
    void    PrettyPrint_ (long long int v, const TextOutputStream& out)
    {
        wchar_t buf[1024];
        ::swprintf (buf, NEltsOf (buf), L"%lld", v);
        out.Write (buf);
    }
    void    PrettyPrint_ (unsigned long long int v, const TextOutputStream& out)
    {
        wchar_t buf[1024];
        ::swprintf (buf, NEltsOf (buf), L"%llu", v);
        out.Write (buf);
    }
    void    PrettyPrint_ (long double v, const TextOutputStream& out)
    {
        wchar_t buf[1024];
        ::swprintf (buf, NEltsOf (buf), L"%Lf", v);
        Assert (::wcslen (buf) >= 1);
        // trim trailing 0
        for (size_t i = ::wcslen (buf) - 1; buf[i] == '0'; --i) {
            if (i >= 0 and buf[i - 1] != '.') {
                buf[i] = '\0';
            }
        }
        out.Write (buf);
    }
    void    PrettyPrint_ (const wstring& v, const TextOutputStream& out)
    {
        out.Write (L"\"");
        for (auto i = v.begin (); i != v.end (); ++i) {
            switch (*i) {
                case '\"':
                    out.Write (L"\\\"");
                    break;
                case '\\':
                    out.Write (L"\\\\");
                    break;
                case '\n':
                    out.Write (L"\\n");
                    break;
                case '\r':
                    out.Write (L"\\r");
                    break;
// unclear if we need to quote other chars such as \f\t\b\ but probably not...
                default:
                    wchar_t c = *i;
                    out.Write (&c, &c + 1);
                    break;
            }
        }
        out.Write (L"\"");
    }
    void    PrettyPrint_ (const vector<Memory::VariantValue>& v, const TextOutputStream& out, int indentLevel)
    {
        out.Write (L"[\n");
        for (auto i = v.begin (); i != v.end (); ++i) {
            Indent_ (out, indentLevel + 1);
            PrettyPrint_ (*i, out, indentLevel + 1);
            if (i + 1 != v.end ()) {
                out.Write (L",");
            }
            out.Write (L"\n");
        }
        Indent_ (out, indentLevel);
        out.Write (L"]");
    }
    void    PrettyPrint_ (const map<wstring, Memory::VariantValue>& v, const TextOutputStream& out, int indentLevel)
    {
        out.Write (L"{\n");
        for (auto i = v.begin (); i != v.end ();) {
            Indent_ (out, indentLevel + 1);
            PrettyPrint_ (i->first, out, indentLevel + 1);
            out.Write (L" : ");
            PrettyPrint_ (i->second, out, indentLevel + 1);
            ++i;
            if (i != v.end ()) {
                out.Write (L",");
            }
            out.Write (L"\n");
        }
        Indent_ (out, indentLevel);
        out.Write (L"}");
    }
    void    PrettyPrint_ (const Memory::VariantValue& v, const TextOutputStream& out, int indentLevel)
    {
        switch (v.GetType ()) {
            case    Memory::VariantValue::Type::eNull:
                PrettyPrint_Null_ (out);
                break;
            case    Memory::VariantValue::Type::eBoolean:
                PrettyPrint_ (v.As<bool> (), out);
                break;
            case    Memory::VariantValue::Type::eDate:
                PrettyPrint_ (v.As<wstring> (), out);
                break;
            case    Memory::VariantValue::Type::eDateTime:
                PrettyPrint_ (v.As<wstring> (), out);
                break;
            case    Memory::VariantValue::Type::eInteger:
                PrettyPrint_ (v.As<long long int> (), out);
                break;
            case    Memory::VariantValue::Type::eUnsignedInteger:
                PrettyPrint_ (v.As<unsigned long long int> (), out);
                break;
            case    Memory::VariantValue::Type::eFloat:
                PrettyPrint_ (v.As<long double> (), out);
                break;
            case    Memory::VariantValue::Type::eString:
                PrettyPrint_ (v.As<wstring> (), out);
                break;
            case    Memory::VariantValue::Type::eMap:
                PrettyPrint_ (v.As<map<wstring, Memory::VariantValue>> (), out, indentLevel);
                break;
            case    Memory::VariantValue::Type::eArray:
                PrettyPrint_ (v.As<vector<Memory::VariantValue>> (), out, indentLevel);
                break;
            default:
                RequireNotReached ();       // only certain types allowed
        }
    }
}

/*
 ********************************************************************************
 ******************** DataExchangeFormat::JSON::Writer **************************
 ********************************************************************************
 */
class   DataExchangeFormat::JSON::Writer::Rep_ : public DataExchangeFormat::Writer::_IRep {
public:
    DECLARE_USE_BLOCK_ALLOCATION (Rep_);
public:
    virtual _SharedPtrIRep  Clone () const override {
        return _SharedPtrIRep (new Rep_ ());    // no instance data
    }
    virtual void    Write (const Memory::VariantValue& v, const Streams::BinaryOutputStream& out) override {
        PrettyPrint_ (v, TextOutputStreamBinaryAdapter (out, TextOutputStreamBinaryAdapter::Format::eUTF8WithoutBOM), 0);
    }
    virtual void    Write (const Memory::VariantValue& v, const Streams::TextOutputStream& out) override {
        PrettyPrint_ (v, out, 0);
    }
};

DataExchangeFormat::JSON::Writer::Writer ()
    : inherited (shared_ptr<_IRep> (new Rep_ ()))
{
}
<commit_msg>in JSON writer, extra NL at end of mapping & array - maybe makes layout look better (experiment)<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2013.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#include    "../../Streams/iostream/BinaryOutputStreamFromOStreamAdapter.h"
#include    "../../Streams/TextOutputStreamBinaryAdapter.h"

#include    "Writer.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::DataExchangeFormat;
using   namespace   Stroika::Foundation::Streams;

/*
 * TODO:
 *      No known issues
 */

/*
 ********************************************************************************
 *************** DataExchangeFormat::JSON::PrettyPrint **************************
 ********************************************************************************
 */
namespace   {
    void    Indent_ (const TextOutputStream& out, int indentLevel)
    {
        for (int i = 0; i < indentLevel; ++i) {
            out.Write (L"    ");
        }
    }
}
namespace   {
    void    PrettyPrint_ (const Memory::VariantValue& v, const TextOutputStream& out, int indentLevel);
    void    PrettyPrint_Null_ (const TextOutputStream& out)
    {
        out.Write (L"null");
    }
    void    PrettyPrint_ (bool v, const TextOutputStream& out)
    {
        if (v) {
            out.Write (L"true");
        }
        else {
            out.Write (L"false");
        }
    }
    void    PrettyPrint_ (long long int v, const TextOutputStream& out)
    {
        wchar_t buf[1024];
        ::swprintf (buf, NEltsOf (buf), L"%lld", v);
        out.Write (buf);
    }
    void    PrettyPrint_ (unsigned long long int v, const TextOutputStream& out)
    {
        wchar_t buf[1024];
        ::swprintf (buf, NEltsOf (buf), L"%llu", v);
        out.Write (buf);
    }
    void    PrettyPrint_ (long double v, const TextOutputStream& out)
    {
        wchar_t buf[1024];
        ::swprintf (buf, NEltsOf (buf), L"%Lf", v);
        Assert (::wcslen (buf) >= 1);
        // trim trailing 0
        for (size_t i = ::wcslen (buf) - 1; buf[i] == '0'; --i) {
            if (i >= 0 and buf[i - 1] != '.') {
                buf[i] = '\0';
            }
        }
        out.Write (buf);
    }
    void    PrettyPrint_ (const wstring& v, const TextOutputStream& out)
    {
        out.Write (L"\"");
        for (auto i = v.begin (); i != v.end (); ++i) {
            switch (*i) {
                case '\"':
                    out.Write (L"\\\"");
                    break;
                case '\\':
                    out.Write (L"\\\\");
                    break;
                case '\n':
                    out.Write (L"\\n");
                    break;
                case '\r':
                    out.Write (L"\\r");
                    break;
// unclear if we need to quote other chars such as \f\t\b\ but probably not...
                default:
                    wchar_t c = *i;
                    out.Write (&c, &c + 1);
                    break;
            }
        }
        out.Write (L"\"");
    }
    void    PrettyPrint_ (const vector<Memory::VariantValue>& v, const TextOutputStream& out, int indentLevel)
    {
        out.Write (L"[\n");
        for (auto i = v.begin (); i != v.end (); ++i) {
            Indent_ (out, indentLevel + 1);
            PrettyPrint_ (*i, out, indentLevel + 1);
            if (i + 1 != v.end ()) {
                out.Write (L",");
            }
            out.Write (L"\n");
        }
        Indent_ (out, indentLevel);
        out.Write (L"]\n");
    }
    void    PrettyPrint_ (const map<wstring, Memory::VariantValue>& v, const TextOutputStream& out, int indentLevel)
    {
        out.Write (L"{\n");
        for (auto i = v.begin (); i != v.end ();) {
            Indent_ (out, indentLevel + 1);
            PrettyPrint_ (i->first, out, indentLevel + 1);
            out.Write (L" : ");
            PrettyPrint_ (i->second, out, indentLevel + 1);
            ++i;
            if (i != v.end ()) {
                out.Write (L",");
            }
            out.Write (L"\n");
        }
        Indent_ (out, indentLevel);
        out.Write (L"}\n");
    }
    void    PrettyPrint_ (const Memory::VariantValue& v, const TextOutputStream& out, int indentLevel)
    {
        switch (v.GetType ()) {
            case    Memory::VariantValue::Type::eNull:
                PrettyPrint_Null_ (out);
                break;
            case    Memory::VariantValue::Type::eBoolean:
                PrettyPrint_ (v.As<bool> (), out);
                break;
            case    Memory::VariantValue::Type::eDate:
                PrettyPrint_ (v.As<wstring> (), out);
                break;
            case    Memory::VariantValue::Type::eDateTime:
                PrettyPrint_ (v.As<wstring> (), out);
                break;
            case    Memory::VariantValue::Type::eInteger:
                PrettyPrint_ (v.As<long long int> (), out);
                break;
            case    Memory::VariantValue::Type::eUnsignedInteger:
                PrettyPrint_ (v.As<unsigned long long int> (), out);
                break;
            case    Memory::VariantValue::Type::eFloat:
                PrettyPrint_ (v.As<long double> (), out);
                break;
            case    Memory::VariantValue::Type::eString:
                PrettyPrint_ (v.As<wstring> (), out);
                break;
            case    Memory::VariantValue::Type::eMap:
                PrettyPrint_ (v.As<map<wstring, Memory::VariantValue>> (), out, indentLevel);
                break;
            case    Memory::VariantValue::Type::eArray:
                PrettyPrint_ (v.As<vector<Memory::VariantValue>> (), out, indentLevel);
                break;
            default:
                RequireNotReached ();       // only certain types allowed
        }
    }
}

/*
 ********************************************************************************
 ******************** DataExchangeFormat::JSON::Writer **************************
 ********************************************************************************
 */
class   DataExchangeFormat::JSON::Writer::Rep_ : public DataExchangeFormat::Writer::_IRep {
public:
    DECLARE_USE_BLOCK_ALLOCATION (Rep_);
public:
    virtual _SharedPtrIRep  Clone () const override {
        return _SharedPtrIRep (new Rep_ ());    // no instance data
    }
    virtual void    Write (const Memory::VariantValue& v, const Streams::BinaryOutputStream& out) override {
        PrettyPrint_ (v, TextOutputStreamBinaryAdapter (out, TextOutputStreamBinaryAdapter::Format::eUTF8WithoutBOM), 0);
    }
    virtual void    Write (const Memory::VariantValue& v, const Streams::TextOutputStream& out) override {
        PrettyPrint_ (v, out, 0);
    }
};

DataExchangeFormat::JSON::Writer::Writer ()
    : inherited (shared_ptr<_IRep> (new Rep_ ()))
{
}
<|endoftext|>


<commit_before>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
 *
 * 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 "paddle/operators/maxout_op.h"
namespace paddle {
namespace operators {

using framework::Tensor;

class MaxOutOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  MaxOutOpMaker(framework::OpProto* proto, framework::OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput(
        "X",
        "(Tensor) The input tensor of maxout operator. "
        "The format of input tensor is NCHW. Where N is batch size, C is the "
        "number of channels, H and W is the height and width of feature.");
    AddOutput("Out",
              "(Tensor) The output tensor of maxout operator."
              "The format of output tensor is also NCHW."
              "Where N is batch size, C is "
              "the number of channels, H and W is the height and "
              "width of feature.");
    AddAttr<int>(
        "groups",
        R"DOC("Specifies how many groups the input tensor will be split"
        "in the channel dimension. And the number of output channel is "
        "the number of channels divided by groups.."
        )DOC");
    AddComment(R"DOC(
        Assumed the input shape is (N, Ci, H, W).
        The output shape is (N, Co, H, W). Then `Co = Ci / groups`.

       math:
       y_{si+j} = \max_k x_{gsi + sk + j}
       g = groups
       s = input.size / num_channels
       0 \le i < num_channels / groups
       0 \le j < s
       0 \le k < groups

    Please refer to Paper:
      - Maxout Networks: http://www.jmlr.org/proceedings/papers/v28/goodfellow13.pdf
      - Multi-digit Number Recognition from Street View \
        Imagery using Deep Convolutional Neural Networks: \
        https://arxiv.org/pdf/1312.6082v4.pdf
        )DOC");
  }
};

class MaxOutOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;
  void InferShape(framework::InferShapeContext* ctx) const override {
    PADDLE_ENFORCE(ctx->HasInput("X"),
                   "Input(X) of MaxoutOp"
                   "should not be null.");
    PADDLE_ENFORCE(ctx->HasOutput("Out"),
                   "Output(Out) of MaxoutOp should not be null.");
    auto in_x_dims = ctx->GetInputDim("X");
    int groups = ctx->Attrs().Get<int>("groups");
    // check groups > 1
    PADDLE_ENFORCE_GT(groups, 1, "groups should be larger than 1 in maxoutop");
    std::vector<int64_t> output_shape({in_x_dims[0], in_x_dims[1] / groups});
    output_shape.push_back(in_x_dims[2]);
    output_shape.push_back(in_x_dims[3]);
    ctx->SetOutputDim("Out", framework::make_ddim(output_shape));
  }
};

class MaxOutOpGrad : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;
  void InferShape(framework::InferShapeContext* ctx) const override {
    PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) must not be null.");
    PADDLE_ENFORCE(ctx->HasOutput(framework::GradVarName("X")),
                   "Input(X@GRAD) should not be null.");
    ctx->SetOutputDim(framework::GradVarName("X"), ctx->GetInputDim("X"));
  }
};
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
REGISTER_OP(maxout, ops::MaxOutOp, ops::MaxOutOpMaker, maxout_grad,
            ops::MaxOutOpGrad);
REGISTER_OP_CPU_KERNEL(maxout,
                       ops::MaxOutKernel<paddle::platform::CPUPlace, float>);
REGISTER_OP_CPU_KERNEL(
    maxout_grad, ops::MaxOutGradKernel<paddle::platform::CPUPlace, float>);
<commit_msg>fix maxout op latex equation (#6303)<commit_after>/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
 *
 * 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 "paddle/operators/maxout_op.h"
namespace paddle {
namespace operators {

using framework::Tensor;

class MaxOutOpMaker : public framework::OpProtoAndCheckerMaker {
 public:
  MaxOutOpMaker(framework::OpProto* proto, framework::OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput(
        "X",
        "(Tensor) The input tensor of maxout operator. "
        "The format of input tensor is NCHW. Where N is batch size, C is the "
        "number of channels, H and W is the height and width of feature.");
    AddOutput("Out",
              "(Tensor) The output tensor of maxout operator."
              "The format of output tensor is also NCHW."
              "Where N is batch size, C is "
              "the number of channels, H and W is the height and "
              "width of feature.");
    AddAttr<int>(
        "groups",
        R"DOC("Specifies how many groups the input tensor will be split"
        "in the channel dimension. And the number of output channel is "
        "the number of channels divided by groups.."
        )DOC");
    AddComment(R"DOC(
MaxOut Operator.

Assumed the input shape is (N, Ci, H, W).
The output shape is (N, Co, H, W).
Then $Co = Ci / groups$ and the operator formula is as follows:

$$
y_{si+j} = \max_k x_{gsi + sk + j} \\
g = groups \\
s = \frac{input.size}{num\_channels} \\
0 \le i < \frac{num\_channels}{groups} \\
0 \le j < s \\
0 \le k < groups
$$

Please refer to Paper:
  - Maxout Networks: http://www.jmlr.org/proceedings/papers/v28/goodfellow13.pdf
  - Multi-digit Number Recognition from Street View \
    Imagery using Deep Convolutional Neural Networks: \
    https://arxiv.org/pdf/1312.6082v4.pdf

)DOC");
  }
};

class MaxOutOp : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;
  void InferShape(framework::InferShapeContext* ctx) const override {
    PADDLE_ENFORCE(ctx->HasInput("X"),
                   "Input(X) of MaxoutOp"
                   "should not be null.");
    PADDLE_ENFORCE(ctx->HasOutput("Out"),
                   "Output(Out) of MaxoutOp should not be null.");
    auto in_x_dims = ctx->GetInputDim("X");
    int groups = ctx->Attrs().Get<int>("groups");
    // check groups > 1
    PADDLE_ENFORCE_GT(groups, 1, "groups should be larger than 1 in maxoutop");
    std::vector<int64_t> output_shape({in_x_dims[0], in_x_dims[1] / groups});
    output_shape.push_back(in_x_dims[2]);
    output_shape.push_back(in_x_dims[3]);
    ctx->SetOutputDim("Out", framework::make_ddim(output_shape));
  }
};

class MaxOutOpGrad : public framework::OperatorWithKernel {
 public:
  using framework::OperatorWithKernel::OperatorWithKernel;
  void InferShape(framework::InferShapeContext* ctx) const override {
    PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) must not be null.");
    PADDLE_ENFORCE(ctx->HasOutput(framework::GradVarName("X")),
                   "Input(X@GRAD) should not be null.");
    ctx->SetOutputDim(framework::GradVarName("X"), ctx->GetInputDim("X"));
  }
};
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;
REGISTER_OP(maxout, ops::MaxOutOp, ops::MaxOutOpMaker, maxout_grad,
            ops::MaxOutOpGrad);
REGISTER_OP_CPU_KERNEL(maxout,
                       ops::MaxOutKernel<paddle::platform::CPUPlace, float>);
REGISTER_OP_CPU_KERNEL(
    maxout_grad, ops::MaxOutGradKernel<paddle::platform::CPUPlace, float>);
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2011 Francois Beaune
//
// 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.
//

// Interface header.
#include "cameracontroller.h"

// appleseed.renderer headers.
#include "renderer/api/camera.h"
#include "renderer/api/scene.h"
#include "renderer/api/utility.h"

// appleseed.foundation headers.
#include "foundation/math/transform.h"

// Qt headers.
#include <QEvent>
#include <QMouseEvent>
#include <QWidget>

using namespace foundation;
using namespace renderer;

namespace appleseed {
namespace studio {

//
// CameraController class implementation.
//

CameraController::CameraController(
    QWidget*    render_widget,
    Scene*      scene)
  : m_render_widget(render_widget)
  , m_camera(scene->get_camera())
{
    configure_controller(scene);

    m_render_widget->installEventFilter(this);
}

CameraController::~CameraController()
{
    m_render_widget->removeEventFilter(this);

    m_camera->get_parameters().insert("controller_target", m_controller.get_target());
}

void CameraController::update_camera_transform()
{
    m_camera->set_transform(Transformd(m_controller.get_transform()));
}

bool CameraController::eventFilter(QObject* object, QEvent* event)
{
    switch (event->type())
    {
      case QEvent::MouseButtonPress:
        if (handle_mouse_button_press_event(static_cast<QMouseEvent*>(event)))
            return true;
        break;

      case QEvent::MouseButtonRelease:
        if (handle_mouse_button_release_event(static_cast<QMouseEvent*>(event)))
            return true;
        break;

      case QEvent::MouseMove:
        if (handle_mouse_move_event(static_cast<QMouseEvent*>(event)))
            return true;
        break;
    }

    return QObject::eventFilter(object, event);
}

void CameraController::configure_controller(const Scene* scene)
{
    // Set the controller orientation and position based on the scene camera.
    m_controller.set_transform(
        m_camera->get_transform().get_local_to_parent());

    if (m_camera->get_parameters().strings().exist("controller_target"))
    {
        // The camera already has a target position, use it.
        m_controller.set_target(
            m_camera->get_parameters().get_optional<Vector3d>(
                "controller_target",
                Vector3d(0.0)));
    }
    else
    {
        // Otherwise, if the scene is not empty, use its center as the target position.
        const GAABB3 scene_bbox =
            compute_parent_bbox<GAABB3>(
                scene->assembly_instances().begin(),
                scene->assembly_instances().end());
        if (scene_bbox.is_valid())
            m_controller.set_target(Vector3d(scene_bbox.center()));
    }
}

Vector2d CameraController::get_mouse_position(const QMouseEvent* event) const
{
    const int width = m_render_widget->width();
    const int height = m_render_widget->height();

    const double x =  static_cast<double>(event->x()) / width;
    const double y = -static_cast<double>(event->y()) / height;

    return Vector2d(x, y);
}

bool CameraController::handle_mouse_button_press_event(const QMouseEvent* event)
{
    if (m_controller.is_dragging())
        return false;

    if (!(event->modifiers() & Qt::ControlModifier))
        return false;

    const Vector2d position = get_mouse_position(event);

    switch (event->button())
    {
      case Qt::LeftButton:
        m_controller.begin_drag(ControllerType::Tumble, position);
        return true;

      case Qt::MidButton:
        m_controller.begin_drag(ControllerType::Track, position);
        return true;

      case Qt::RightButton:
        m_controller.begin_drag(ControllerType::Dolly, position);
        return true;
    }

    return false;
}

bool CameraController::handle_mouse_button_release_event(const QMouseEvent* event)
{
    if (!m_controller.is_dragging())
        return false;

    m_controller.end_drag();

    return true;
}

bool CameraController::handle_mouse_move_event(const QMouseEvent* event)
{
    if (!m_controller.is_dragging())
        return false;

    const Vector2d position = get_mouse_position(event);

    m_controller.update_drag(position);

    emit signal_camera_changed();

    return true;
}

}   // namespace studio
}   // namespace appleseed
<commit_msg>it is now possible to "track" the camera using the left mouse button + Alt, in addition to the middle mouse button.<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2010-2011 Francois Beaune
//
// 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.
//

// Interface header.
#include "cameracontroller.h"

// appleseed.renderer headers.
#include "renderer/api/camera.h"
#include "renderer/api/scene.h"
#include "renderer/api/utility.h"

// appleseed.foundation headers.
#include "foundation/math/transform.h"

// Qt headers.
#include <QEvent>
#include <QMouseEvent>
#include <QWidget>

using namespace foundation;
using namespace renderer;

namespace appleseed {
namespace studio {

//
// CameraController class implementation.
//

CameraController::CameraController(
    QWidget*    render_widget,
    Scene*      scene)
  : m_render_widget(render_widget)
  , m_camera(scene->get_camera())
{
    configure_controller(scene);

    m_render_widget->installEventFilter(this);
}

CameraController::~CameraController()
{
    m_render_widget->removeEventFilter(this);

    m_camera->get_parameters().insert("controller_target", m_controller.get_target());
}

void CameraController::update_camera_transform()
{
    m_camera->set_transform(Transformd(m_controller.get_transform()));
}

bool CameraController::eventFilter(QObject* object, QEvent* event)
{
    switch (event->type())
    {
      case QEvent::MouseButtonPress:
        if (handle_mouse_button_press_event(static_cast<QMouseEvent*>(event)))
            return true;
        break;

      case QEvent::MouseButtonRelease:
        if (handle_mouse_button_release_event(static_cast<QMouseEvent*>(event)))
            return true;
        break;

      case QEvent::MouseMove:
        if (handle_mouse_move_event(static_cast<QMouseEvent*>(event)))
            return true;
        break;
    }

    return QObject::eventFilter(object, event);
}

void CameraController::configure_controller(const Scene* scene)
{
    // Set the controller orientation and position based on the scene camera.
    m_controller.set_transform(
        m_camera->get_transform().get_local_to_parent());

    if (m_camera->get_parameters().strings().exist("controller_target"))
    {
        // The camera already has a target position, use it.
        m_controller.set_target(
            m_camera->get_parameters().get_optional<Vector3d>(
                "controller_target",
                Vector3d(0.0)));
    }
    else
    {
        // Otherwise, if the scene is not empty, use its center as the target position.
        const GAABB3 scene_bbox =
            compute_parent_bbox<GAABB3>(
                scene->assembly_instances().begin(),
                scene->assembly_instances().end());
        if (scene_bbox.is_valid())
            m_controller.set_target(Vector3d(scene_bbox.center()));
    }
}

Vector2d CameraController::get_mouse_position(const QMouseEvent* event) const
{
    const int width = m_render_widget->width();
    const int height = m_render_widget->height();

    const double x =  static_cast<double>(event->x()) / width;
    const double y = -static_cast<double>(event->y()) / height;

    return Vector2d(x, y);
}

bool CameraController::handle_mouse_button_press_event(const QMouseEvent* event)
{
    if (m_controller.is_dragging())
        return false;

    if (!(event->modifiers() & Qt::ControlModifier))
        return false;

    const Vector2d position = get_mouse_position(event);

    switch (event->button())
    {
      case Qt::LeftButton:
        m_controller.begin_drag(
            (event->modifiers() & Qt::AltModifier) ? ControllerType::Track : ControllerType::Tumble,
            position);
        return true;

      case Qt::MidButton:
        m_controller.begin_drag(ControllerType::Track, position);
        return true;

      case Qt::RightButton:
        m_controller.begin_drag(ControllerType::Dolly, position);
        return true;
    }

    return false;
}

bool CameraController::handle_mouse_button_release_event(const QMouseEvent* event)
{
    if (!m_controller.is_dragging())
        return false;

    m_controller.end_drag();

    return true;
}

bool CameraController::handle_mouse_move_event(const QMouseEvent* event)
{
    if (!m_controller.is_dragging())
        return false;

    const Vector2d position = get_mouse_position(event);

    m_controller.update_drag(position);

    emit signal_camera_changed();

    return true;
}

}   // namespace studio
}   // namespace appleseed
<|endoftext|>


<commit_before>#pragma once

#include <functional>
#include <vector>
#include <string>

namespace GUI {
    /// A window where a hymn can be selected.
    class SelectHymnWindow {
        public:
            /// Constructor.
            SelectHymnWindow();

            /// Scan the save directory for hymns.
            void Scan();

            /// Show the window and let the user select a hymn.
            void Show();

            /// Set function to call when closed.
            /**
             * @param callback Function to call when window is closed.
             */
            void SetClosedCallback(std::function<void(const std::string&)> callback);

            /// Get whether the window is visible.
            /**
             * @return Whether the window is visible.
             */
            bool IsVisible() const;

            /// Set whether the window should be visible.
            /**
             * @param visible Whether the window should be visible.
             */
            void SetVisible(bool visible);

            /// Set window title.
            /**
             * @param title Window title.
             */
            void SetTitle(const char* title);

            /// Set the name of the open button.
            /**
             * @param openButtonName The name of the open button.
             */
            void SetOpenButtonName(const char* openButtonName);

        private:
            // Interaction
            bool hasClosedCallback = false;
            std::function<void(const std::string&)> closedCallback;

            std::vector<std::string> files;
            char name[128] = "";

            bool visible = false;

            const char* title;
            const char* openButtonName;
    };
}
<commit_msg>Proper initialization of character array.<commit_after>#pragma once

#include <functional>
#include <vector>
#include <string>

namespace GUI {
    /// A window where a hymn can be selected.
    class SelectHymnWindow {
        public:
            /// Constructor.
            SelectHymnWindow();

            /// Scan the save directory for hymns.
            void Scan();

            /// Show the window and let the user select a hymn.
            void Show();

            /// Set function to call when closed.
            /**
             * @param callback Function to call when window is closed.
             */
            void SetClosedCallback(std::function<void(const std::string&)> callback);

            /// Get whether the window is visible.
            /**
             * @return Whether the window is visible.
             */
            bool IsVisible() const;

            /// Set whether the window should be visible.
            /**
             * @param visible Whether the window should be visible.
             */
            void SetVisible(bool visible);

            /// Set window title.
            /**
             * @param title Window title.
             */
            void SetTitle(const char* title);

            /// Set the name of the open button.
            /**
             * @param openButtonName The name of the open button.
             */
            void SetOpenButtonName(const char* openButtonName);

        private:
            // Interaction
            bool hasClosedCallback = false;
            std::function<void(const std::string&)> closedCallback;

            std::vector<std::string> files;
            char name[128] = {'\0'};

            bool visible = false;

            const char* title;
            const char* openButtonName;
    };
}
<|endoftext|>


<commit_before>//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for expressions involving
//  pseudo-object references.  Pseudo-objects are conceptual objects
//  whose storage is entirely abstract and all accesses to which are
//  translated through some sort of abstraction barrier.
//
//  For example, Objective-C objects can have "properties", either
//  declared or undeclared.  A property may be accessed by writing
//    expr.prop
//  where 'expr' is an r-value of Objective-C pointer type and 'prop'
//  is the name of the property.  If this expression is used in a context
//  needing an r-value, it is treated as if it were a message-send
//  of the associated 'getter' selector, typically:
//    [expr prop]
//  If it is used as the LHS of a simple assignment, it is treated
//  as a message-send of the associated 'setter' selector, typically:
//    [expr setProp: RHS]
//  If it is used as the LHS of a compound assignment, or the operand
//  of a unary increment or decrement, both are required;  for example,
//  'expr.prop *= 100' would be translated to:
//    [expr setProp: [expr prop] * 100]
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Initialization.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"

using namespace clang;
using namespace sema;

static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
                                            const ObjCPropertyRefExpr *PRE) {
  bool instanceProperty;
  QualType searchType;
  if (PRE->isObjectReceiver()) {
    searchType = PRE->getBase()->getType()
      ->castAs<ObjCObjectPointerType>()->getPointeeType();
    instanceProperty = true;
  } else if (PRE->isSuperReceiver()) {
    searchType = PRE->getSuperReceiverType();
    instanceProperty = false;
    if (const ObjCObjectPointerType *PT
        = searchType->getAs<ObjCObjectPointerType>()) {
      searchType = PT->getPointeeType();
      instanceProperty = true;
    }
  } else if (PRE->isClassReceiver()) {
    searchType = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
    instanceProperty = false;
  }

  return S.LookupMethodInObjectType(sel, searchType, instanceProperty);
}

ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
  assert(E->getValueKind() == VK_LValue &&
         E->getObjectKind() == OK_ObjCProperty);
  const ObjCPropertyRefExpr *PRE = E->getObjCProperty();

  QualType ReceiverType;
  if (PRE->isObjectReceiver())
    ReceiverType = PRE->getBase()->getType();
  else if (PRE->isSuperReceiver())
    ReceiverType = PRE->getSuperReceiverType();
  else
    ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver());

  ExprValueKind VK = VK_RValue;
  QualType T;
  if (PRE->isImplicitProperty()) {
    if (ObjCMethodDecl *GetterMethod =
          PRE->getImplicitPropertyGetter()) {
      T = getMessageSendResultType(ReceiverType, GetterMethod,
                                   PRE->isClassReceiver(),
                                   PRE->isSuperReceiver());
      VK = Expr::getValueKindForType(GetterMethod->getResultType());
    } else {
      Diag(PRE->getLocation(), diag::err_getter_not_found)
            << PRE->getBase()->getType();
      return ExprError();
    }
  } else {
    ObjCPropertyDecl *prop = PRE->getExplicitProperty();

    ObjCMethodDecl *getter =
      LookupMethodInReceiverType(*this, prop->getGetterName(), PRE);
    if (getter && !getter->hasRelatedResultType())
      DiagnosePropertyAccessorMismatch(prop, getter, PRE->getLocation());
    if (!getter) getter = prop->getGetterMethodDecl();

    // Figure out the type of the expression.  Mostly this is the
    // result type of the getter, if possible.
    if (getter) {
      T = getMessageSendResultType(ReceiverType, getter,
                                   PRE->isClassReceiver(),
                                   PRE->isSuperReceiver());
      VK = Expr::getValueKindForType(getter->getResultType());

      // As a special case, if the method returns 'id', try to get a
      // better type from the property.
      if (VK == VK_RValue && T->isObjCIdType() &&
          prop->getType()->isObjCRetainableType())
        T = prop->getType();
    } else {
      T = prop->getType();
      VK = Expr::getValueKindForType(T);
      T = T.getNonLValueExprType(Context);
    }
  }

  E->setType(T);
  E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, E, 0, VK);

  ExprResult Result = MaybeBindToTemporary(E);
  if (!Result.isInvalid())
    E = Result.take();

  return Owned(E);
}

namespace {
  struct PseudoObjectInfo {
    const ObjCPropertyRefExpr *RefExpr;
    bool HasSetter;
    Selector SetterSelector;
    ParmVarDecl *SetterParam;
    QualType SetterParamType;

    void setSetter(ObjCMethodDecl *setter) {
      HasSetter = true;
      SetterParam = *setter->param_begin();
      SetterParamType = SetterParam->getType().getUnqualifiedType();
    }

    PseudoObjectInfo(Sema &S, Expr *E)
      : RefExpr(E->getObjCProperty()), HasSetter(false), SetterParam(0) {

      assert(E->getValueKind() == VK_LValue &&
             E->getObjectKind() == OK_ObjCProperty);

      // Try to find a setter.

      // For implicit properties, just trust the lookup we already did.
      if (RefExpr->isImplicitProperty()) {
        if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
          setSetter(setter);
          SetterSelector = setter->getSelector();
        } else {
          IdentifierInfo *getterName =
            RefExpr->getImplicitPropertyGetter()->getSelector()
              .getIdentifierInfoForSlot(0);
          SetterSelector =
            SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
                                               S.PP.getSelectorTable(),
                                               getterName);
        }
        return;
      }

      // For explicit properties, this is more involved.
      ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
      SetterSelector = prop->getSetterName();

      // Do a normal method lookup first.
      if (ObjCMethodDecl *setter =
            LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
        setSetter(setter);
        return;
      }

      // If that failed, trust the type on the @property declaration.
      if (!prop->isReadOnly()) {
        HasSetter = true;
        SetterParamType = prop->getType().getUnqualifiedType();
      }
    }
  };
}

/// Check an increment or decrement of a pseudo-object expression.
ExprResult Sema::checkPseudoObjectIncDec(Scope *S, SourceLocation opcLoc,
                                         UnaryOperatorKind opcode, Expr *op) {
  assert(UnaryOperator::isIncrementDecrementOp(opcode));
  PseudoObjectInfo info(*this, op);

  // If there's no setter, we have no choice but to try to assign to
  // the result of the getter.
  if (!info.HasSetter) {
    QualType resultType = info.RefExpr->getGetterResultType();
    assert(!resultType.isNull() && "property has no setter and no getter!");

    // Only do this if the getter returns an l-value reference type.
    if (const LValueReferenceType *refType
          = resultType->getAs<LValueReferenceType>()) {
      op = ImplicitCastExpr::Create(Context, refType->getPointeeType(),
                                    CK_GetObjCProperty, op, 0, VK_LValue);
      return BuildUnaryOp(S, opcLoc, opcode, op);
    }

    // Otherwise, it's an error.
    Diag(opcLoc, diag::err_nosetter_property_incdec)
      << unsigned(info.RefExpr->isImplicitProperty())
      << unsigned(UnaryOperator::isDecrementOp(opcode))
      << info.SetterSelector
      << op->getSourceRange();
    return ExprError();
  }

  // ++/-- behave like compound assignments, i.e. they need a getter.
  QualType getterResultType = info.RefExpr->getGetterResultType();
  if (getterResultType.isNull()) {
    assert(info.RefExpr->isImplicitProperty());
    Diag(opcLoc, diag::err_nogetter_property_incdec)
      << unsigned(UnaryOperator::isDecrementOp(opcode))
      << info.RefExpr->getImplicitPropertyGetter()->getSelector()
      << op->getSourceRange();
    return ExprError();
  }

  // HACK: change the type of the operand to prevent further placeholder
  // transformation.
  op->setType(getterResultType.getNonLValueExprType(Context));
  op->setObjectKind(OK_Ordinary);

  ExprResult result = CreateBuiltinUnaryOp(opcLoc, opcode, op);
  if (result.isInvalid()) return ExprError();

  // Change the object kind back.
  op->setObjectKind(OK_ObjCProperty);
  return result;
}

ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
                                             BinaryOperatorKind opcode,
                                             Expr *LHS, Expr *RHS) {
  assert(BinaryOperator::isAssignmentOp(opcode));
  PseudoObjectInfo info(*this, LHS);

  // If there's no setter, we have no choice but to try to assign to
  // the result of the getter.
  if (!info.HasSetter) {
    QualType resultType = info.RefExpr->getGetterResultType();
    assert(!resultType.isNull() && "property has no setter and no getter!");

    // Only do this if the getter returns an l-value reference type.
    if (const LValueReferenceType *refType
          = resultType->getAs<LValueReferenceType>()) {
      LHS = ImplicitCastExpr::Create(Context, refType->getPointeeType(),
                                     CK_GetObjCProperty, LHS, 0, VK_LValue);
      return BuildBinOp(S, opcLoc, opcode, LHS, RHS);
    }

    // Otherwise, it's an error.
    Diag(opcLoc, diag::err_nosetter_property_assignment)
      << unsigned(info.RefExpr->isImplicitProperty())
      << info.SetterSelector
      << LHS->getSourceRange() << RHS->getSourceRange();
    return ExprError();
  }

  // If there is a setter, we definitely want to use it.

  // If this is a simple assignment, just initialize the parameter
  // with the RHS.
  if (opcode == BO_Assign) {
    LHS->setType(info.SetterParamType.getNonLValueExprType(Context));

    // Under certain circumstances, we need to type-check the RHS as a
    // straight-up parameter initialization.  This gives somewhat
    // inferior diagnostics, so we try to avoid it.

    if (RHS->isTypeDependent()) {
      // Just build the expression.

    } else if ((getLangOptions().CPlusPlus && LHS->getType()->isRecordType()) ||
               (getLangOptions().ObjCAutoRefCount &&
                info.SetterParam &&
                info.SetterParam->hasAttr<NSConsumedAttr>())) {
      InitializedEntity param = (info.SetterParam
        ? InitializedEntity::InitializeParameter(Context, info.SetterParam)
        : InitializedEntity::InitializeParameter(Context, info.SetterParamType,
                                                 /*consumed*/ false));
      ExprResult arg = PerformCopyInitialization(param, opcLoc, RHS);
      if (arg.isInvalid()) return ExprError();
      RHS = arg.take();

      // Warn about assignments of +1 objects to unsafe pointers in ARC.
      // CheckAssignmentOperands does this on the other path.
      if (getLangOptions().ObjCAutoRefCount)
        checkUnsafeExprAssigns(opcLoc, LHS, RHS);
    } else {
      ExprResult RHSResult = Owned(RHS);

      LHS->setObjectKind(OK_Ordinary);
      QualType resultType = CheckAssignmentOperands(LHS, RHSResult, opcLoc,
                                                    /*compound*/ QualType());
      LHS->setObjectKind(OK_ObjCProperty);

      if (!RHSResult.isInvalid()) RHS = RHSResult.take();
      if (resultType.isNull()) return ExprError();
    }

    // Warn about property sets in ARC that might cause retain cycles.
    if (getLangOptions().ObjCAutoRefCount && !info.RefExpr->isSuperReceiver())
      checkRetainCycles(const_cast<Expr*>(info.RefExpr->getBase()), RHS);

    return new (Context) BinaryOperator(LHS, RHS, opcode, RHS->getType(),
                                        RHS->getValueKind(),
                                        RHS->getObjectKind(),
                                        opcLoc);
  }

  // If this is a compound assignment, we need to use the getter, too.
  QualType getterResultType = info.RefExpr->getGetterResultType();
  if (getterResultType.isNull()) {
    Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
      << LHS->getSourceRange() << RHS->getSourceRange();
    return ExprError();
  }

  // HACK: change the type of the LHS to prevent further placeholder
  // transformation.
  LHS->setType(getterResultType.getNonLValueExprType(Context));
  LHS->setObjectKind(OK_Ordinary);

  ExprResult result = CreateBuiltinBinOp(opcLoc, opcode, LHS, RHS);
  if (result.isInvalid()) return ExprError();

  // Change the object kind back.
  LHS->setObjectKind(OK_ObjCProperty);
  return result;
}
<commit_msg>Reflow code. No intended functionality change.<commit_after>//===--- SemaPseudoObject.cpp - Semantic Analysis for Pseudo-Objects ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for expressions involving
//  pseudo-object references.  Pseudo-objects are conceptual objects
//  whose storage is entirely abstract and all accesses to which are
//  translated through some sort of abstraction barrier.
//
//  For example, Objective-C objects can have "properties", either
//  declared or undeclared.  A property may be accessed by writing
//    expr.prop
//  where 'expr' is an r-value of Objective-C pointer type and 'prop'
//  is the name of the property.  If this expression is used in a context
//  needing an r-value, it is treated as if it were a message-send
//  of the associated 'getter' selector, typically:
//    [expr prop]
//  If it is used as the LHS of a simple assignment, it is treated
//  as a message-send of the associated 'setter' selector, typically:
//    [expr setProp: RHS]
//  If it is used as the LHS of a compound assignment, or the operand
//  of a unary increment or decrement, both are required;  for example,
//  'expr.prop *= 100' would be translated to:
//    [expr setProp: [expr prop] * 100]
//
//===----------------------------------------------------------------------===//

#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Initialization.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Lex/Preprocessor.h"

using namespace clang;
using namespace sema;

static ObjCMethodDecl *LookupMethodInReceiverType(Sema &S, Selector sel,
                                            const ObjCPropertyRefExpr *PRE) {
  if (PRE->isObjectReceiver()) {
    const ObjCObjectPointerType *PT =
      PRE->getBase()->getType()->castAs<ObjCObjectPointerType>();
    return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);
  }

  if (PRE->isSuperReceiver()) {
    if (const ObjCObjectPointerType *PT =
        PRE->getSuperReceiverType()->getAs<ObjCObjectPointerType>())
      return S.LookupMethodInObjectType(sel, PT->getPointeeType(), true);

    return S.LookupMethodInObjectType(sel, PRE->getSuperReceiverType(), false);
  }

  assert(PRE->isClassReceiver() && "Invalid expression");
  QualType IT = S.Context.getObjCInterfaceType(PRE->getClassReceiver());
  return S.LookupMethodInObjectType(sel, IT, false);
}

ExprResult Sema::checkPseudoObjectRValue(Expr *E) {
  assert(E->getValueKind() == VK_LValue &&
         E->getObjectKind() == OK_ObjCProperty);
  const ObjCPropertyRefExpr *PRE = E->getObjCProperty();

  QualType ReceiverType;
  if (PRE->isObjectReceiver())
    ReceiverType = PRE->getBase()->getType();
  else if (PRE->isSuperReceiver())
    ReceiverType = PRE->getSuperReceiverType();
  else
    ReceiverType = Context.getObjCInterfaceType(PRE->getClassReceiver());

  ExprValueKind VK = VK_RValue;
  QualType T;
  if (PRE->isImplicitProperty()) {
    if (ObjCMethodDecl *GetterMethod =
          PRE->getImplicitPropertyGetter()) {
      T = getMessageSendResultType(ReceiverType, GetterMethod,
                                   PRE->isClassReceiver(),
                                   PRE->isSuperReceiver());
      VK = Expr::getValueKindForType(GetterMethod->getResultType());
    } else {
      Diag(PRE->getLocation(), diag::err_getter_not_found)
            << PRE->getBase()->getType();
      return ExprError();
    }
  } else {
    ObjCPropertyDecl *prop = PRE->getExplicitProperty();

    ObjCMethodDecl *getter =
      LookupMethodInReceiverType(*this, prop->getGetterName(), PRE);
    if (getter && !getter->hasRelatedResultType())
      DiagnosePropertyAccessorMismatch(prop, getter, PRE->getLocation());
    if (!getter) getter = prop->getGetterMethodDecl();

    // Figure out the type of the expression.  Mostly this is the
    // result type of the getter, if possible.
    if (getter) {
      T = getMessageSendResultType(ReceiverType, getter,
                                   PRE->isClassReceiver(),
                                   PRE->isSuperReceiver());
      VK = Expr::getValueKindForType(getter->getResultType());

      // As a special case, if the method returns 'id', try to get a
      // better type from the property.
      if (VK == VK_RValue && T->isObjCIdType() &&
          prop->getType()->isObjCRetainableType())
        T = prop->getType();
    } else {
      T = prop->getType();
      VK = Expr::getValueKindForType(T);
      T = T.getNonLValueExprType(Context);
    }
  }

  E->setType(T);
  E = ImplicitCastExpr::Create(Context, T, CK_GetObjCProperty, E, 0, VK);

  ExprResult Result = MaybeBindToTemporary(E);
  if (!Result.isInvalid())
    E = Result.take();

  return Owned(E);
}

namespace {
  struct PseudoObjectInfo {
    const ObjCPropertyRefExpr *RefExpr;
    bool HasSetter;
    Selector SetterSelector;
    ParmVarDecl *SetterParam;
    QualType SetterParamType;

    void setSetter(ObjCMethodDecl *setter) {
      HasSetter = true;
      SetterParam = *setter->param_begin();
      SetterParamType = SetterParam->getType().getUnqualifiedType();
    }

    PseudoObjectInfo(Sema &S, Expr *E)
      : RefExpr(E->getObjCProperty()), HasSetter(false), SetterParam(0) {

      assert(E->getValueKind() == VK_LValue &&
             E->getObjectKind() == OK_ObjCProperty);

      // Try to find a setter.

      // For implicit properties, just trust the lookup we already did.
      if (RefExpr->isImplicitProperty()) {
        if (ObjCMethodDecl *setter = RefExpr->getImplicitPropertySetter()) {
          setSetter(setter);
          SetterSelector = setter->getSelector();
        } else {
          IdentifierInfo *getterName =
            RefExpr->getImplicitPropertyGetter()->getSelector()
              .getIdentifierInfoForSlot(0);
          SetterSelector =
            SelectorTable::constructSetterName(S.PP.getIdentifierTable(),
                                               S.PP.getSelectorTable(),
                                               getterName);
        }
        return;
      }

      // For explicit properties, this is more involved.
      ObjCPropertyDecl *prop = RefExpr->getExplicitProperty();
      SetterSelector = prop->getSetterName();

      // Do a normal method lookup first.
      if (ObjCMethodDecl *setter =
            LookupMethodInReceiverType(S, SetterSelector, RefExpr)) {
        setSetter(setter);
        return;
      }

      // If that failed, trust the type on the @property declaration.
      if (!prop->isReadOnly()) {
        HasSetter = true;
        SetterParamType = prop->getType().getUnqualifiedType();
      }
    }
  };
}

/// Check an increment or decrement of a pseudo-object expression.
ExprResult Sema::checkPseudoObjectIncDec(Scope *S, SourceLocation opcLoc,
                                         UnaryOperatorKind opcode, Expr *op) {
  assert(UnaryOperator::isIncrementDecrementOp(opcode));
  PseudoObjectInfo info(*this, op);

  // If there's no setter, we have no choice but to try to assign to
  // the result of the getter.
  if (!info.HasSetter) {
    QualType resultType = info.RefExpr->getGetterResultType();
    assert(!resultType.isNull() && "property has no setter and no getter!");

    // Only do this if the getter returns an l-value reference type.
    if (const LValueReferenceType *refType
          = resultType->getAs<LValueReferenceType>()) {
      op = ImplicitCastExpr::Create(Context, refType->getPointeeType(),
                                    CK_GetObjCProperty, op, 0, VK_LValue);
      return BuildUnaryOp(S, opcLoc, opcode, op);
    }

    // Otherwise, it's an error.
    Diag(opcLoc, diag::err_nosetter_property_incdec)
      << unsigned(info.RefExpr->isImplicitProperty())
      << unsigned(UnaryOperator::isDecrementOp(opcode))
      << info.SetterSelector
      << op->getSourceRange();
    return ExprError();
  }

  // ++/-- behave like compound assignments, i.e. they need a getter.
  QualType getterResultType = info.RefExpr->getGetterResultType();
  if (getterResultType.isNull()) {
    assert(info.RefExpr->isImplicitProperty());
    Diag(opcLoc, diag::err_nogetter_property_incdec)
      << unsigned(UnaryOperator::isDecrementOp(opcode))
      << info.RefExpr->getImplicitPropertyGetter()->getSelector()
      << op->getSourceRange();
    return ExprError();
  }

  // HACK: change the type of the operand to prevent further placeholder
  // transformation.
  op->setType(getterResultType.getNonLValueExprType(Context));
  op->setObjectKind(OK_Ordinary);

  ExprResult result = CreateBuiltinUnaryOp(opcLoc, opcode, op);
  if (result.isInvalid()) return ExprError();

  // Change the object kind back.
  op->setObjectKind(OK_ObjCProperty);
  return result;
}

ExprResult Sema::checkPseudoObjectAssignment(Scope *S, SourceLocation opcLoc,
                                             BinaryOperatorKind opcode,
                                             Expr *LHS, Expr *RHS) {
  assert(BinaryOperator::isAssignmentOp(opcode));
  PseudoObjectInfo info(*this, LHS);

  // If there's no setter, we have no choice but to try to assign to
  // the result of the getter.
  if (!info.HasSetter) {
    QualType resultType = info.RefExpr->getGetterResultType();
    assert(!resultType.isNull() && "property has no setter and no getter!");

    // Only do this if the getter returns an l-value reference type.
    if (const LValueReferenceType *refType
          = resultType->getAs<LValueReferenceType>()) {
      LHS = ImplicitCastExpr::Create(Context, refType->getPointeeType(),
                                     CK_GetObjCProperty, LHS, 0, VK_LValue);
      return BuildBinOp(S, opcLoc, opcode, LHS, RHS);
    }

    // Otherwise, it's an error.
    Diag(opcLoc, diag::err_nosetter_property_assignment)
      << unsigned(info.RefExpr->isImplicitProperty())
      << info.SetterSelector
      << LHS->getSourceRange() << RHS->getSourceRange();
    return ExprError();
  }

  // If there is a setter, we definitely want to use it.

  // If this is a simple assignment, just initialize the parameter
  // with the RHS.
  if (opcode == BO_Assign) {
    LHS->setType(info.SetterParamType.getNonLValueExprType(Context));

    // Under certain circumstances, we need to type-check the RHS as a
    // straight-up parameter initialization.  This gives somewhat
    // inferior diagnostics, so we try to avoid it.

    if (RHS->isTypeDependent()) {
      // Just build the expression.

    } else if ((getLangOptions().CPlusPlus && LHS->getType()->isRecordType()) ||
               (getLangOptions().ObjCAutoRefCount &&
                info.SetterParam &&
                info.SetterParam->hasAttr<NSConsumedAttr>())) {
      InitializedEntity param = (info.SetterParam
        ? InitializedEntity::InitializeParameter(Context, info.SetterParam)
        : InitializedEntity::InitializeParameter(Context, info.SetterParamType,
                                                 /*consumed*/ false));
      ExprResult arg = PerformCopyInitialization(param, opcLoc, RHS);
      if (arg.isInvalid()) return ExprError();
      RHS = arg.take();

      // Warn about assignments of +1 objects to unsafe pointers in ARC.
      // CheckAssignmentOperands does this on the other path.
      if (getLangOptions().ObjCAutoRefCount)
        checkUnsafeExprAssigns(opcLoc, LHS, RHS);
    } else {
      ExprResult RHSResult = Owned(RHS);

      LHS->setObjectKind(OK_Ordinary);
      QualType resultType = CheckAssignmentOperands(LHS, RHSResult, opcLoc,
                                                    /*compound*/ QualType());
      LHS->setObjectKind(OK_ObjCProperty);

      if (!RHSResult.isInvalid()) RHS = RHSResult.take();
      if (resultType.isNull()) return ExprError();
    }

    // Warn about property sets in ARC that might cause retain cycles.
    if (getLangOptions().ObjCAutoRefCount && !info.RefExpr->isSuperReceiver())
      checkRetainCycles(const_cast<Expr*>(info.RefExpr->getBase()), RHS);

    return new (Context) BinaryOperator(LHS, RHS, opcode, RHS->getType(),
                                        RHS->getValueKind(),
                                        RHS->getObjectKind(),
                                        opcLoc);
  }

  // If this is a compound assignment, we need to use the getter, too.
  QualType getterResultType = info.RefExpr->getGetterResultType();
  if (getterResultType.isNull()) {
    Diag(opcLoc, diag::err_nogetter_property_compound_assignment)
      << LHS->getSourceRange() << RHS->getSourceRange();
    return ExprError();
  }

  // HACK: change the type of the LHS to prevent further placeholder
  // transformation.
  LHS->setType(getterResultType.getNonLValueExprType(Context));
  LHS->setObjectKind(OK_Ordinary);

  ExprResult result = CreateBuiltinBinOp(opcLoc, opcode, LHS, RHS);
  if (result.isInvalid()) return ExprError();

  // Change the object kind back.
  LHS->setObjectKind(OK_ObjCProperty);
  return result;
}
<|endoftext|>


<commit_before>/*
  HardwareSerial.cpp - Hardware serial library for Wiring
  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

  Modified 23 November 2006 by David A. Mellis
  Modified 28 September 2010 by Mark Sproul
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "wiring.h"
#include "wiring_private.h"

// this next line disables the entire HardwareSerial.cpp,
// this is so I can support Attiny series and any other chip without a uart
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)

#include "HardwareSerial.h"

// Define constants and variables for buffering incoming serial data.  We're
// using a ring buffer (I think), in which rx_buffer_head is the index of the
// location to which to write the next incoming character and rx_buffer_tail
// is the index of the location from which to read.
#if (RAMEND < 1000)
  #define RX_BUFFER_SIZE 32
#else
  #define RX_BUFFER_SIZE 128
#endif

struct ring_buffer
{
  unsigned char buffer[RX_BUFFER_SIZE];
  int head;
  int tail;
};

#if defined(UBRRH) || defined(UBRR0H)
  ring_buffer rx_buffer  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR1H)
  ring_buffer rx_buffer1  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR2H)
  ring_buffer rx_buffer2  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR3H)
  ring_buffer rx_buffer3  =  { { 0 }, 0, 0 };
#endif

inline void store_char(unsigned char c, ring_buffer *rx_buffer)
{
  int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != rx_buffer->tail) {
    rx_buffer->buffer[rx_buffer->head] = c;
    rx_buffer->head = i;
  }
}

#if defined(USART_RX_vect)
  SIGNAL(USART_RX_vect)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8535
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_USART0_RECV) && defined(UDR0)
  SIGNAL(SIG_USART0_RECV)
  {
    unsigned char c  =  UDR0;
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_UART0_RECV) && defined(UDR0)
  SIGNAL(SIG_UART0_RECV)
  {
    unsigned char c  =  UDR0;
    store_char(c, &rx_buffer);
  }
//#elif defined(SIG_USART_RECV)
#elif defined(USART0_RX_vect)
  // fixed by Mark Sproul this is on the 644/644p
  //SIGNAL(SIG_USART_RECV)
  SIGNAL(USART0_RX_vect)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8, atmega32
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_UART_RECV)
  // this is for atmega8
  SIGNAL(SIG_UART_RECV)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;  //  atmega645
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(USBCON)
  #warning No interrupt handler for usart 0
  #warning Serial(0) is on USB interface
#else
  #error No interrupt handler for usart 0
#endif

//#if defined(SIG_USART1_RECV)
#if defined(USART1_RX_vect)
  //SIGNAL(SIG_USART1_RECV)
  SIGNAL(USART1_RX_vect)
  {
    unsigned char c = UDR1;
    store_char(c, &rx_buffer1);
  }
#elif defined(SIG_USART1_RECV)
  #error SIG_USART1_RECV
#endif

#if defined(USART2_RX_vect) && defined(UDR2)
  SIGNAL(USART2_RX_vect)
  {
    unsigned char c = UDR2;
    store_char(c, &rx_buffer2);
  }
#elif defined(SIG_USART2_RECV)
  #error SIG_USART2_RECV
#endif

#if defined(USART3_RX_vect) && defined(UDR3)
  SIGNAL(USART3_RX_vect)
  {
    unsigned char c = UDR3;
    store_char(c, &rx_buffer3);
  }
#elif defined(SIG_USART3_RECV)
  #error SIG_USART3_RECV
#endif

// Constructors ////////////////////////////////////////////////////////////////

HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
  volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
  volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
  volatile uint8_t *udr,
  uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x)
{
  _rx_buffer = rx_buffer;
  _ubrrh = ubrrh;
  _ubrrl = ubrrl;
  _ucsra = ucsra;
  _ucsrb = ucsrb;
  _udr = udr;
  _rxen = rxen;
  _txen = txen;
  _rxcie = rxcie;
  _udre = udre;
  _u2x = u2x;
}

// Public Methods //////////////////////////////////////////////////////////////

void HardwareSerial::begin(unsigned long baud)
{
  uint16_t baud_setting;
  bool use_u2x = true;

#if F_CPU == 16000000UL
  // hardcoded exception for compatibility with the bootloader shipped
  // with the Duemilanove and previous boards and the firmware on the 8U2
  // on the Uno and Mega 2560.
  if (baud == 57600) {
    use_u2x = false;
  }
#endif

  if (use_u2x) {
    *_ucsra = 1 << _u2x;
    baud_setting = (F_CPU / 4 / baud - 1) / 2;
  } else {
    *_ucsra = 0;
    baud_setting = (F_CPU / 8 / baud - 1) / 2;
  }

  // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
  *_ubrrh = baud_setting >> 8;
  *_ubrrl = baud_setting;

  sbi(*_ucsrb, _rxen);
  sbi(*_ucsrb, _txen);
  sbi(*_ucsrb, _rxcie);
}

void HardwareSerial::end()
{
  cbi(*_ucsrb, _rxen);
  cbi(*_ucsrb, _txen);
  cbi(*_ucsrb, _rxcie);
}

int HardwareSerial::available(void)
{
  return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE;
}

int HardwareSerial::peek(void)
{
  if (_rx_buffer->head == _rx_buffer->tail) {
    return -1;
  } else {
    return _rx_buffer->buffer[_rx_buffer->tail];
  }
}

int HardwareSerial::read(void)
{
  // if the head isn't ahead of the tail, we don't have any characters
  if (_rx_buffer->head == _rx_buffer->tail) {
    return -1;
  } else {
    unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
    _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE;
    return c;
  }
}

void HardwareSerial::flush()
{
  // don't reverse this or there may be problems if the RX interrupt
  // occurs after reading the value of rx_buffer_head but before writing
  // the value to rx_buffer_tail; the previous value of rx_buffer_head
  // may be written to rx_buffer_tail, making it appear as if the buffer
  // don't reverse this or there may be problems if the RX interrupt
  // occurs after reading the value of rx_buffer_head but before writing
  // the value to rx_buffer_tail; the previous value of rx_buffer_head
  // may be written to rx_buffer_tail, making it appear as if the buffer
  // were full, not empty.
  _rx_buffer->head = _rx_buffer->tail;
}

void HardwareSerial::write(uint8_t c)
{
  while (!((*_ucsra) & (1 << _udre)))
    ;

  *_udr = c;
}

// Preinstantiate Objects //////////////////////////////////////////////////////

#if defined(UBRRH) && defined(UBRRL)
  HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X);
#elif defined(UBRR0H) && defined(UBRR0L)
  HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0);
#elif defined(USBCON)
  #warning no serial port defined  (port 0)
#else
  #error no serial port defined  (port 0)
#endif

#if defined(UBRR1H)
  HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1);
#endif
#if defined(UBRR2H)
  HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2);
#endif
#if defined(UBRR3H)
  HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3);
#endif

#endif // whole file

<commit_msg>Fixing 300 baud communication for serial.<commit_after>/*
  HardwareSerial.cpp - Hardware serial library for Wiring
  Copyright (c) 2006 Nicholas Zambetti.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

  Modified 23 November 2006 by David A. Mellis
  Modified 28 September 2010 by Mark Sproul
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "wiring.h"
#include "wiring_private.h"

// this next line disables the entire HardwareSerial.cpp,
// this is so I can support Attiny series and any other chip without a uart
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)

#include "HardwareSerial.h"

// Define constants and variables for buffering incoming serial data.  We're
// using a ring buffer (I think), in which rx_buffer_head is the index of the
// location to which to write the next incoming character and rx_buffer_tail
// is the index of the location from which to read.
#if (RAMEND < 1000)
  #define RX_BUFFER_SIZE 32
#else
  #define RX_BUFFER_SIZE 128
#endif

struct ring_buffer
{
  unsigned char buffer[RX_BUFFER_SIZE];
  int head;
  int tail;
};

#if defined(UBRRH) || defined(UBRR0H)
  ring_buffer rx_buffer  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR1H)
  ring_buffer rx_buffer1  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR2H)
  ring_buffer rx_buffer2  =  { { 0 }, 0, 0 };
#endif
#if defined(UBRR3H)
  ring_buffer rx_buffer3  =  { { 0 }, 0, 0 };
#endif

inline void store_char(unsigned char c, ring_buffer *rx_buffer)
{
  int i = (unsigned int)(rx_buffer->head + 1) % RX_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != rx_buffer->tail) {
    rx_buffer->buffer[rx_buffer->head] = c;
    rx_buffer->head = i;
  }
}

#if defined(USART_RX_vect)
  SIGNAL(USART_RX_vect)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8535
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_USART0_RECV) && defined(UDR0)
  SIGNAL(SIG_USART0_RECV)
  {
    unsigned char c  =  UDR0;
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_UART0_RECV) && defined(UDR0)
  SIGNAL(SIG_UART0_RECV)
  {
    unsigned char c  =  UDR0;
    store_char(c, &rx_buffer);
  }
//#elif defined(SIG_USART_RECV)
#elif defined(USART0_RX_vect)
  // fixed by Mark Sproul this is on the 644/644p
  //SIGNAL(SIG_USART_RECV)
  SIGNAL(USART0_RX_vect)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8, atmega32
  #else
    #error UDR not defined
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(SIG_UART_RECV)
  // this is for atmega8
  SIGNAL(SIG_UART_RECV)
  {
  #if defined(UDR0)
    unsigned char c  =  UDR0;  //  atmega645
  #elif defined(UDR)
    unsigned char c  =  UDR;  //  atmega8
  #endif
    store_char(c, &rx_buffer);
  }
#elif defined(USBCON)
  #warning No interrupt handler for usart 0
  #warning Serial(0) is on USB interface
#else
  #error No interrupt handler for usart 0
#endif

//#if defined(SIG_USART1_RECV)
#if defined(USART1_RX_vect)
  //SIGNAL(SIG_USART1_RECV)
  SIGNAL(USART1_RX_vect)
  {
    unsigned char c = UDR1;
    store_char(c, &rx_buffer1);
  }
#elif defined(SIG_USART1_RECV)
  #error SIG_USART1_RECV
#endif

#if defined(USART2_RX_vect) && defined(UDR2)
  SIGNAL(USART2_RX_vect)
  {
    unsigned char c = UDR2;
    store_char(c, &rx_buffer2);
  }
#elif defined(SIG_USART2_RECV)
  #error SIG_USART2_RECV
#endif

#if defined(USART3_RX_vect) && defined(UDR3)
  SIGNAL(USART3_RX_vect)
  {
    unsigned char c = UDR3;
    store_char(c, &rx_buffer3);
  }
#elif defined(SIG_USART3_RECV)
  #error SIG_USART3_RECV
#endif

// Constructors ////////////////////////////////////////////////////////////////

HardwareSerial::HardwareSerial(ring_buffer *rx_buffer,
  volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
  volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
  volatile uint8_t *udr,
  uint8_t rxen, uint8_t txen, uint8_t rxcie, uint8_t udre, uint8_t u2x)
{
  _rx_buffer = rx_buffer;
  _ubrrh = ubrrh;
  _ubrrl = ubrrl;
  _ucsra = ucsra;
  _ucsrb = ucsrb;
  _udr = udr;
  _rxen = rxen;
  _txen = txen;
  _rxcie = rxcie;
  _udre = udre;
  _u2x = u2x;
}

// Public Methods //////////////////////////////////////////////////////////////

void HardwareSerial::begin(unsigned long baud)
{
  uint16_t baud_setting;
  bool use_u2x = true;

#if F_CPU == 16000000UL
  // hardcoded exception for compatibility with the bootloader shipped
  // with the Duemilanove and previous boards and the firmware on the 8U2
  // on the Uno and Mega 2560.
  if (baud == 57600) {
    use_u2x = false;
  }
#endif

try_again:

  if (use_u2x) {
    *_ucsra = 1 << _u2x;
    baud_setting = (F_CPU / 4 / baud - 1) / 2;
  } else {
    *_ucsra = 0;
    baud_setting = (F_CPU / 8 / baud - 1) / 2;
  }

  if ((baud_setting > 4095) && use_u2x)
  {
    use_u2x = false;
    goto try_again;
  }

  // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
  *_ubrrh = baud_setting >> 8;
  *_ubrrl = baud_setting;

  sbi(*_ucsrb, _rxen);
  sbi(*_ucsrb, _txen);
  sbi(*_ucsrb, _rxcie);
}

void HardwareSerial::end()
{
  cbi(*_ucsrb, _rxen);
  cbi(*_ucsrb, _txen);
  cbi(*_ucsrb, _rxcie);
}

int HardwareSerial::available(void)
{
  return (unsigned int)(RX_BUFFER_SIZE + _rx_buffer->head - _rx_buffer->tail) % RX_BUFFER_SIZE;
}

int HardwareSerial::peek(void)
{
  if (_rx_buffer->head == _rx_buffer->tail) {
    return -1;
  } else {
    return _rx_buffer->buffer[_rx_buffer->tail];
  }
}

int HardwareSerial::read(void)
{
  // if the head isn't ahead of the tail, we don't have any characters
  if (_rx_buffer->head == _rx_buffer->tail) {
    return -1;
  } else {
    unsigned char c = _rx_buffer->buffer[_rx_buffer->tail];
    _rx_buffer->tail = (unsigned int)(_rx_buffer->tail + 1) % RX_BUFFER_SIZE;
    return c;
  }
}

void HardwareSerial::flush()
{
  // don't reverse this or there may be problems if the RX interrupt
  // occurs after reading the value of rx_buffer_head but before writing
  // the value to rx_buffer_tail; the previous value of rx_buffer_head
  // may be written to rx_buffer_tail, making it appear as if the buffer
  // don't reverse this or there may be problems if the RX interrupt
  // occurs after reading the value of rx_buffer_head but before writing
  // the value to rx_buffer_tail; the previous value of rx_buffer_head
  // may be written to rx_buffer_tail, making it appear as if the buffer
  // were full, not empty.
  _rx_buffer->head = _rx_buffer->tail;
}

void HardwareSerial::write(uint8_t c)
{
  while (!((*_ucsra) & (1 << _udre)))
    ;

  *_udr = c;
}

// Preinstantiate Objects //////////////////////////////////////////////////////

#if defined(UBRRH) && defined(UBRRL)
  HardwareSerial Serial(&rx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UDR, RXEN, TXEN, RXCIE, UDRE, U2X);
#elif defined(UBRR0H) && defined(UBRR0L)
  HardwareSerial Serial(&rx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UDR0, RXEN0, TXEN0, RXCIE0, UDRE0, U2X0);
#elif defined(USBCON)
  #warning no serial port defined  (port 0)
#else
  #error no serial port defined  (port 0)
#endif

#if defined(UBRR1H)
  HardwareSerial Serial1(&rx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UDR1, RXEN1, TXEN1, RXCIE1, UDRE1, U2X1);
#endif
#if defined(UBRR2H)
  HardwareSerial Serial2(&rx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UDR2, RXEN2, TXEN2, RXCIE2, UDRE2, U2X2);
#endif
#if defined(UBRR3H)
  HardwareSerial Serial3(&rx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UDR3, RXEN3, TXEN3, RXCIE3, UDRE3, U2X3);
#endif

#endif // whole file

<|endoftext|>