<commit_before>#ifndef PIXELBOOST_DISABLE_GRAPHICS

#include <algorithm>
#include <set>

#include "pixelboost/graphics/camera/camera.h"
#include "pixelboost/graphics/camera/viewport.h"
#include "pixelboost/graphics/device/device.h"
#include "pixelboost/graphics/effect/effect.h"
#include "pixelboost/graphics/effect/manager.h"
#include "pixelboost/graphics/renderer/common/irenderer.h"
#include "pixelboost/graphics/renderer/common/renderable.h"
#include "pixelboost/graphics/renderer/common/renderer.h"

using namespace pb;

Renderer* Renderer::Renderer::_Instance = 0;

Renderer::Renderer()
{
    _Instance = this;

    _EffectManager = new EffectManager();
}

Renderer::~Renderer()
{
    _Instance = 0;
}

Renderer* Renderer::Instance()
{
    return _Instance;
}

void Renderer::Render()
{
    for (ViewportList::iterator it = _Viewports.begin(); it != _Viewports.end(); ++it)
    {
        (*it)->Render();

        FlushBuffer(*it);
    }
}

EffectManager* Renderer::GetEffectManager()
{
    return _EffectManager;
}

void Renderer::AttachRenderable(Renderable* renderable)
{
    _Renderables[renderable->GetLayer()].push_back(renderable);
}

void Renderer::AddViewport(Viewport* viewport)
{
    _Viewports.push_back(viewport);
}

void Renderer::RemoveViewport(Viewport* viewport)
{
    for (ViewportList::iterator it = _Viewports.begin(); it != _Viewports.end(); ++it)
    {
        if (*it == viewport)
        {
            _Viewports.erase(it);
            return;
        }
    }
}

void Renderer::SetHandler(int renderableType, IRenderer* renderer)
{
    _RenderableHandlers[renderableType] = renderer;
}

bool RenderableBackToFrontSorter(const Renderable* a, const Renderable* b)
{
    return a->GetMVP()[3][2] > b->GetMVP()[3][2];
}

void Renderer::FlushBuffer(Viewport* viewport)
{
    for (int i=0; i<16; i++)
    {
        RenderableList& renderables = _Renderables[i];

        if (!renderables.size())
            continue;

        for (RenderableList::iterator it = renderables.begin(); it != renderables.end(); ++it)
        {
            (*it)->CalculateMVP(viewport);
        }

        std::stable_sort(renderables.begin(), renderables.end(), &RenderableBackToFrontSorter);

        Uid type = renderables[0]->GetRenderableType();
        Effect* effect = renderables[0]->GetEffect();
        int start = 0;
        int count = 0;

        for (int i=0; i < renderables.size(); i++)
        {
            Uid newType = renderables[i]->GetRenderableType();
            Effect* newEffect = renderables[i]->GetEffect();

            if (type == newType && effect == newEffect)
            {
                count++;
            } else {
                RenderBatch(viewport, count, &renderables[start], effect);
                start = i;
                count = 1;
                type = newType;
                effect = newEffect;
            }
        }

        if (count > 0)
        {
            RenderBatch(viewport, count, &renderables[start], effect);
        }
    }

    _Renderables.clear();
}

void Renderer::RenderBatch(Viewport* viewport, int count, Renderable** renderable, Effect* effect)
{
    if (!effect)
        return;

    RenderableHandlerMap::iterator it = _RenderableHandlers.find(renderable[0]->GetRenderableType());

    if (it != _RenderableHandlers.end())
    {
        EffectTechnique* technique = effect->GetTechnique(viewport->GetRenderScheme());

        if (!technique)
        {
            for (int i=0; i < count; i++)
            {
                technique = viewport->GetTechnique(renderable[i], effect);

                if (technique)
                {
                    for (int j=0; j<technique->GetNumPasses(); j++)
                    {
                        EffectPass* pass = technique->GetPass(j);
                        pass->Bind();
                        it->second->Render(1, &renderable[i], viewport, pass);
                    }
                }
            }
        } else
        {
            for (int i=0; i<technique->GetNumPasses(); i++)
            {
                EffectPass* pass = technique->GetPass(i);
                pass->Bind();
                it->second->Render(count, renderable, viewport, pass);
            }
        }
    }
}

#endif
<commit_msg>Fix compiler warning<commit_after>#ifndef PIXELBOOST_DISABLE_GRAPHICS

#include <algorithm>
#include <set>

#include "pixelboost/graphics/camera/camera.h"
#include "pixelboost/graphics/camera/viewport.h"
#include "pixelboost/graphics/device/device.h"
#include "pixelboost/graphics/effect/effect.h"
#include "pixelboost/graphics/effect/manager.h"
#include "pixelboost/graphics/renderer/common/irenderer.h"
#include "pixelboost/graphics/renderer/common/renderable.h"
#include "pixelboost/graphics/renderer/common/renderer.h"

using namespace pb;

Renderer* Renderer::Renderer::_Instance = 0;

Renderer::Renderer()
{
    _Instance = this;

    _EffectManager = new EffectManager();
}

Renderer::~Renderer()
{
    _Instance = 0;
}

Renderer* Renderer::Instance()
{
    return _Instance;
}

void Renderer::Render()
{
    for (ViewportList::iterator it = _Viewports.begin(); it != _Viewports.end(); ++it)
    {
        (*it)->Render();

        FlushBuffer(*it);
    }
}

EffectManager* Renderer::GetEffectManager()
{
    return _EffectManager;
}

void Renderer::AttachRenderable(Renderable* renderable)
{
    _Renderables[renderable->GetLayer()].push_back(renderable);
}

void Renderer::AddViewport(Viewport* viewport)
{
    _Viewports.push_back(viewport);
}

void Renderer::RemoveViewport(Viewport* viewport)
{
    for (ViewportList::iterator it = _Viewports.begin(); it != _Viewports.end(); ++it)
    {
        if (*it == viewport)
        {
            _Viewports.erase(it);
            return;
        }
    }
}

void Renderer::SetHandler(int renderableType, IRenderer* renderer)
{
    _RenderableHandlers[renderableType] = renderer;
}

static bool RenderableBackToFrontSorter(const Renderable* a, const Renderable* b)
{
    return a->GetMVP()[3][2] > b->GetMVP()[3][2];
}

void Renderer::FlushBuffer(Viewport* viewport)
{
    for (int i=0; i<16; i++)
    {
        RenderableList& renderables = _Renderables[i];

        if (!renderables.size())
            continue;

        for (RenderableList::iterator it = renderables.begin(); it != renderables.end(); ++it)
        {
            (*it)->CalculateMVP(viewport);
        }

        std::stable_sort(renderables.begin(), renderables.end(), &RenderableBackToFrontSorter);

        Uid type = renderables[0]->GetRenderableType();
        Effect* effect = renderables[0]->GetEffect();
        int start = 0;
        int count = 0;

        for (int i=0; i < renderables.size(); i++)
        {
            Uid newType = renderables[i]->GetRenderableType();
            Effect* newEffect = renderables[i]->GetEffect();

            if (type == newType && effect == newEffect)
            {
                count++;
            } else {
                RenderBatch(viewport, count, &renderables[start], effect);
                start = i;
                count = 1;
                type = newType;
                effect = newEffect;
            }
        }

        if (count > 0)
        {
            RenderBatch(viewport, count, &renderables[start], effect);
        }
    }

    _Renderables.clear();
}

void Renderer::RenderBatch(Viewport* viewport, int count, Renderable** renderable, Effect* effect)
{
    if (!effect)
        return;

    RenderableHandlerMap::iterator it = _RenderableHandlers.find(renderable[0]->GetRenderableType());

    if (it != _RenderableHandlers.end())
    {
        EffectTechnique* technique = effect->GetTechnique(viewport->GetRenderScheme());

        if (!technique)
        {
            for (int i=0; i < count; i++)
            {
                technique = viewport->GetTechnique(renderable[i], effect);

                if (technique)
                {
                    for (int j=0; j<technique->GetNumPasses(); j++)
                    {
                        EffectPass* pass = technique->GetPass(j);
                        pass->Bind();
                        it->second->Render(1, &renderable[i], viewport, pass);
                    }
                }
            }
        } else
        {
            for (int i=0; i<technique->GetNumPasses(); i++)
            {
                EffectPass* pass = technique->GetPass(i);
                pass->Bind();
                it->second->Render(count, renderable, viewport, pass);
            }
        }
    }
}

#endif
<|endoftext|>


<commit_before>#include <osg/DrawPixels>

using namespace osg;

DrawPixels::DrawPixels()
{
    // turn off display lists right now, just incase we want to modify the projection matrix along the way.
    setSupportsDisplayList(false);

    _position.set(0.0f,0.0f,0.0f);

    _useSubImage = false;
    _offsetX = 0;
    _offsetY = 0;
    _width = 0;
    _height = 0;
}

DrawPixels::DrawPixels(const DrawPixels& drawimage,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
    Drawable(drawimage,copyop),
    _position(drawimage._position),
    _image(drawimage._image),
    _useSubImage(drawimage._useSubImage),
    _offsetX(drawimage._offsetX),
    _offsetY(drawimage._offsetY),
    _width(drawimage._width),
    _height(drawimage._height)
{
}

DrawPixels::~DrawPixels()
{
    // image will delete itself thanks to ref_ptr :-)
}

void DrawPixels::setPosition(const osg::Vec3& position)
{
    _position = position;
    dirtyBound();
}

void DrawPixels::setSubImageDimensions(unsigned int offsetX,unsigned int offsetY,unsigned int width,unsigned int height)
{
    _useSubImage = true;
    _offsetX = offsetX;
    _offsetY = offsetY;
    _width = width;
    _height = height;
}

void DrawPixels::getSubImageDimensions(unsigned int& offsetX,unsigned int& offsetY,unsigned int& width,unsigned int& height) const
{
    offsetX = _offsetX;
    offsetY = _offsetY;
    width = _width;
    height = _height;
}

const bool DrawPixels::computeBound() const
{
    // really needs to be dependant of view poistion and projection... will implement simple version right now.
    _bbox.init();
    float diagonal = 0.0f;
    if (_useSubImage)
    {
        diagonal = sqrtf(_width*_width+_height*_height);
    }
    else
    {
        diagonal = sqrtf(_image->s()*_image->s()+_image->t()*_image->t());
    }

    _bbox.expandBy(_position-osg::Vec3(diagonal,diagonal,diagonal));
    _bbox.expandBy(_position+osg::Vec3(diagonal,diagonal,diagonal));
    _bbox_computed = true;
    return true;
}

void DrawPixels::drawImmediateMode(State&)
{
    glRasterPos3f(_position.x(),_position.y(),_position.z());

    if (_useSubImage)
    {
        const GLvoid* pixels = _image->data();
        glDrawPixels(_width,_height,
                     (GLenum)_image->pixelFormat(),
                     (GLenum)_image->dataType(),
                     pixels);
    }
    else
    {
        glDrawPixels(_image->s(), _image->t(),
                     (GLenum)_image->pixelFormat(),
                     (GLenum)_image->dataType(),
                     _image->data() );
    }
}

<commit_msg>Fix for Win32 build.<commit_after>#include <osg/DrawPixels>

using namespace osg;

DrawPixels::DrawPixels()
{
    // turn off display lists right now, just incase we want to modify the projection matrix along the way.
    setSupportsDisplayList(false);

    _position.set(0.0f,0.0f,0.0f);

    _useSubImage = false;
    _offsetX = 0;
    _offsetY = 0;
    _width = 0;
    _height = 0;
}

DrawPixels::DrawPixels(const DrawPixels& drawimage,const CopyOp& copyop):
    Drawable(drawimage,copyop),
    _position(drawimage._position),
    _image(drawimage._image),
    _useSubImage(drawimage._useSubImage),
    _offsetX(drawimage._offsetX),
    _offsetY(drawimage._offsetY),
    _width(drawimage._width),
    _height(drawimage._height)
{
}

DrawPixels::~DrawPixels()
{
    // image will delete itself thanks to ref_ptr :-)
}

void DrawPixels::setPosition(const osg::Vec3& position)
{
    _position = position;
    dirtyBound();
}

void DrawPixels::setSubImageDimensions(unsigned int offsetX,unsigned int offsetY,unsigned int width,unsigned int height)
{
    _useSubImage = true;
    _offsetX = offsetX;
    _offsetY = offsetY;
    _width = width;
    _height = height;
}

void DrawPixels::getSubImageDimensions(unsigned int& offsetX,unsigned int& offsetY,unsigned int& width,unsigned int& height) const
{
    offsetX = _offsetX;
    offsetY = _offsetY;
    width = _width;
    height = _height;
}

const bool DrawPixels::computeBound() const
{
    // really needs to be dependant of view poistion and projection... will implement simple version right now.
    _bbox.init();
    float diagonal = 0.0f;
    if (_useSubImage)
    {
        diagonal = sqrtf(_width*_width+_height*_height);
    }
    else
    {
        diagonal = sqrtf(_image->s()*_image->s()+_image->t()*_image->t());
    }

    _bbox.expandBy(_position-osg::Vec3(diagonal,diagonal,diagonal));
    _bbox.expandBy(_position+osg::Vec3(diagonal,diagonal,diagonal));
    _bbox_computed = true;
    return true;
}

void DrawPixels::drawImmediateMode(State&)
{
    glRasterPos3f(_position.x(),_position.y(),_position.z());

    if (_useSubImage)
    {
        const GLvoid* pixels = _image->data();
        glDrawPixels(_width,_height,
                     (GLenum)_image->pixelFormat(),
                     (GLenum)_image->dataType(),
                     pixels);
    }
    else
    {
        glDrawPixels(_image->s(), _image->t(),
                     (GLenum)_image->pixelFormat(),
                     (GLenum)_image->dataType(),
                     _image->data() );
    }
}

<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgUI/LineEdit>
#include <osgText/String>
#include <osgText/Font>
#include <osgText/Text>
#include <osg/Notify>
#include <osg/ValueObject>

using namespace osgUI;

LineEdit::LineEdit()
{
}

LineEdit::LineEdit(const osgUI::LineEdit& label, const osg::CopyOp& copyop):
    Widget(label, copyop),
    _text(label._text)
{
}

bool LineEdit::handleImplementation(osgGA::EventVisitor* /*ev*/, osgGA::Event* event)
{
    if (!getHasEventFocus()) return false;

    osgGA::GUIEventAdapter* ea = event->asGUIEventAdapter();
    if (!ea) return false;

    switch(ea->getEventType())
    {
        case(osgGA::GUIEventAdapter::KEYDOWN):
            if (ea->getKey()==osgGA::GUIEventAdapter::KEY_BackSpace ||
                ea->getKey()==osgGA::GUIEventAdapter::KEY_Delete)
            {
                if (!_text.empty())
                {
                    setText(_text.substr(0, _text.size()-1));
                    return true;

                }
            }
            else if (ea->getKey()>=32 && ea->getKey()<=0xff00)
            {
                setText(_text + std::string::value_type(ea->getKey()));
                return true;
            }
            else if (ea->getKey()==osgGA::GUIEventAdapter::KEY_Return )
            {
                if (_validator.valid())
                {
                    std::string text_copy(_text);
                    int cursorpos;
                    if (_validator->validate(text_copy, cursorpos)==Validator::INTERMEDIATE)
                    {
                        _validator->fixup(text_copy);
                    }
                    if (text_copy!=_text) setText(text_copy);
                }

                returnPressed();
                return true;
            }

            OSG_NOTICE<<"Key pressed : "<<ea->getKey()<<std::endl;

            break;
        default:
            break;
    }

    return false;
}

void LineEdit::setText(const std::string& text)
{
    if (_text==text) return;

    std::string text_copy(text);
    if (_validator.valid())
    {
        int cursorpos = 0;
        Validator::State state = _validator->validate(text_copy, cursorpos);
        if (state==Validator::INVALID) return;
    }

    _text = text_copy;

    textChanged(_text);

    if (_textDrawable) _textDrawable->setText(_text);
}

void LineEdit::enterImplementation()
{
    OSG_NOTICE<<"LineEdit enter"<<std::endl;
    if (_backgroundSwitch.valid()) _backgroundSwitch->setSingleChildOn(1);
}

void LineEdit::leaveImplementation()
{
    OSG_NOTICE<<"LineEdit leave"<<std::endl;
    if (_backgroundSwitch.valid()) _backgroundSwitch->setSingleChildOn(0);
}

void LineEdit::textChanged(const std::string& text)
{
    osg::CallbackObject* co = getCallbackObject(this, "textChanged");
    if (co)
    {
        osg::Parameters inputParameters, outputParameters;
        inputParameters.push_back(new osg::StringValueObject("text",text));
        if (co->run(this, inputParameters, outputParameters))
        {
            return;
        }
    }
    textChangedImplementation(text);
}

void LineEdit::textChangedImplementation(const std::string& text)
{
    OSG_NOTICE<<"textChangedImplementation("<<text<<")"<<std::endl;
}

void LineEdit::returnPressedImplementation()
{
    OSG_NOTICE<<"returnPressedImplementation()"<<std::endl;
}

void LineEdit::createGraphicsImplementation()
{
    Style* style = (getStyle()!=0) ? getStyle() : Style::instance().get();

    osg::ref_ptr<osg::Group> group = new osg::Group;

    osg::BoundingBox extents(_extents);
    float unFocused = 0.92;
    float withFocus = 0.97;

    osg::Vec4 frameColor(unFocused,unFocused,unFocused,1.0f);

    bool requiresFrame = (getFrameSettings() && getFrameSettings()->getShape()!=osgUI::FrameSettings::NO_FRAME);
    if (requiresFrame)
    {
        group->addChild(style->createFrame(_extents, getFrameSettings(), frameColor));
        extents.xMin() += getFrameSettings()->getLineWidth();
        extents.xMax() -= getFrameSettings()->getLineWidth();
        extents.yMin() += getFrameSettings()->getLineWidth();
        extents.yMax() -= getFrameSettings()->getLineWidth();
    }

    // clear background of edit region
    _backgroundSwitch = new osg::Switch;
    _backgroundSwitch->addChild(style->createPanel(extents, osg::Vec4(unFocused, unFocused,unFocused, 1.0)));
    _backgroundSwitch->addChild(style->createPanel(extents, osg::Vec4(withFocus, withFocus, withFocus,1.0)));
    _backgroundSwitch->setSingleChildOn(0);
    group->addChild(_backgroundSwitch.get());

    osg::ref_ptr<Node> node = style->createText(extents, getAlignmentSettings(), getTextSettings(), _text);
    _textDrawable = dynamic_cast<osgText::Text*>(node.get());
    _textDrawable->setDataVariance(osg::Object::DYNAMIC);
    group->addChild(node.get());

    style->setupClipStateSet(_extents, getOrCreateWidgetStateSet());

    setGraphicsSubgraph(0, group.get());
}
<commit_msg>Fixed handling of when dynamic_cast<> returns NULL<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2014 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgUI/LineEdit>
#include <osgText/String>
#include <osgText/Font>
#include <osgText/Text>
#include <osg/Notify>
#include <osg/ValueObject>

using namespace osgUI;

LineEdit::LineEdit()
{
}

LineEdit::LineEdit(const osgUI::LineEdit& label, const osg::CopyOp& copyop):
    Widget(label, copyop),
    _text(label._text)
{
}

bool LineEdit::handleImplementation(osgGA::EventVisitor* /*ev*/, osgGA::Event* event)
{
    if (!getHasEventFocus()) return false;

    osgGA::GUIEventAdapter* ea = event->asGUIEventAdapter();
    if (!ea) return false;

    switch(ea->getEventType())
    {
        case(osgGA::GUIEventAdapter::KEYDOWN):
            if (ea->getKey()==osgGA::GUIEventAdapter::KEY_BackSpace ||
                ea->getKey()==osgGA::GUIEventAdapter::KEY_Delete)
            {
                if (!_text.empty())
                {
                    setText(_text.substr(0, _text.size()-1));
                    return true;

                }
            }
            else if (ea->getKey()>=32 && ea->getKey()<=0xff00)
            {
                setText(_text + std::string::value_type(ea->getKey()));
                return true;
            }
            else if (ea->getKey()==osgGA::GUIEventAdapter::KEY_Return )
            {
                if (_validator.valid())
                {
                    std::string text_copy(_text);
                    int cursorpos;
                    if (_validator->validate(text_copy, cursorpos)==Validator::INTERMEDIATE)
                    {
                        _validator->fixup(text_copy);
                    }
                    if (text_copy!=_text) setText(text_copy);
                }

                returnPressed();
                return true;
            }

            OSG_NOTICE<<"Key pressed : "<<ea->getKey()<<std::endl;

            break;
        default:
            break;
    }

    return false;
}

void LineEdit::setText(const std::string& text)
{
    if (_text==text) return;

    std::string text_copy(text);
    if (_validator.valid())
    {
        int cursorpos = 0;
        Validator::State state = _validator->validate(text_copy, cursorpos);
        if (state==Validator::INVALID) return;
    }

    _text = text_copy;

    textChanged(_text);

    if (_textDrawable) _textDrawable->setText(_text);
}

void LineEdit::enterImplementation()
{
    OSG_NOTICE<<"LineEdit enter"<<std::endl;
    if (_backgroundSwitch.valid()) _backgroundSwitch->setSingleChildOn(1);
}

void LineEdit::leaveImplementation()
{
    OSG_NOTICE<<"LineEdit leave"<<std::endl;
    if (_backgroundSwitch.valid()) _backgroundSwitch->setSingleChildOn(0);
}

void LineEdit::textChanged(const std::string& text)
{
    osg::CallbackObject* co = getCallbackObject(this, "textChanged");
    if (co)
    {
        osg::Parameters inputParameters, outputParameters;
        inputParameters.push_back(new osg::StringValueObject("text",text));
        if (co->run(this, inputParameters, outputParameters))
        {
            return;
        }
    }
    textChangedImplementation(text);
}

void LineEdit::textChangedImplementation(const std::string& text)
{
    OSG_NOTICE<<"textChangedImplementation("<<text<<")"<<std::endl;
}

void LineEdit::returnPressedImplementation()
{
    OSG_NOTICE<<"returnPressedImplementation()"<<std::endl;
}

void LineEdit::createGraphicsImplementation()
{
    Style* style = (getStyle()!=0) ? getStyle() : Style::instance().get();

    osg::ref_ptr<osg::Group> group = new osg::Group;

    osg::BoundingBox extents(_extents);
    float unFocused = 0.92;
    float withFocus = 0.97;

    osg::Vec4 frameColor(unFocused,unFocused,unFocused,1.0f);

    bool requiresFrame = (getFrameSettings() && getFrameSettings()->getShape()!=osgUI::FrameSettings::NO_FRAME);
    if (requiresFrame)
    {
        group->addChild(style->createFrame(_extents, getFrameSettings(), frameColor));
        extents.xMin() += getFrameSettings()->getLineWidth();
        extents.xMax() -= getFrameSettings()->getLineWidth();
        extents.yMin() += getFrameSettings()->getLineWidth();
        extents.yMax() -= getFrameSettings()->getLineWidth();
    }

    // clear background of edit region
    _backgroundSwitch = new osg::Switch;
    _backgroundSwitch->addChild(style->createPanel(extents, osg::Vec4(unFocused, unFocused,unFocused, 1.0)));
    _backgroundSwitch->addChild(style->createPanel(extents, osg::Vec4(withFocus, withFocus, withFocus,1.0)));
    _backgroundSwitch->setSingleChildOn(0);
    group->addChild(_backgroundSwitch.get());

    osg::ref_ptr<Node> node = style->createText(extents, getAlignmentSettings(), getTextSettings(), _text);
    _textDrawable = dynamic_cast<osgText::Text*>(node.get());
    node->setDataVariance(osg::Object::DYNAMIC);
    group->addChild(node.get());

    style->setupClipStateSet(_extents, getOrCreateWidgetStateSet());

    setGraphicsSubgraph(0, group.get());
}
<|endoftext|>


<commit_before>#include "TextureFont.hpp"
#include FT_LCD_FILTER_H
#include FT_STROKER_H

using namespace rffalcon;

#define POINT_RES 64
#define DPI 72

TextureFont::TextureFont(std::shared_ptr<TextureAtlas> atlas, const float pointSize, const std::string &filename)
	: _atlas(atlas), _pointSize(pointSize), _filename(filename)
{
	_lcdWeights[0] = 0x10;
	_lcdWeights[0] = 0x40;
	_lcdWeights[0] = 0x70;
	_lcdWeights[0] = 0x40;
	_lcdWeights[0] = 0x10;
	_initialize();
}

TextureFont::~TextureFont()
{
}

float TextureFont::getHeight() const
{
	return _height;
}

void TextureFont::loadGlyphs(const std::string &text)
{
	int width = _atlas->getWidth();
	int height = _atlas->getHeight();
	int depth = _atlas->getDepth();

	FT_Library library;
	FT_Face face;
	FT_Error error = FT_Init_FreeType(&library);
	if (error != FT_Err_Ok) { throw new std::exception(); }

	_loadFace(library, &face);

	FT_Int32 flags = _getFlags();
	int length = text.length();
	// Load the glyph for each character in the string
	for (int i = 0; i < length; ++i)
	{
		char charCode = text[i];
		if (_shouldLoadGlyph(charCode))
		{
			_setFiltering(library);
			FT_UInt glyphIndex = FT_Get_Char_Index(face, charCode);
			error = FT_Load_Glyph(face, glyphIndex, flags);
			if (error) { throw new std::exception(); }
			GlyphLocation glyphLocation = _getGlyphLocation(library, face);
			s1::ivec4 region = _atlas->getRegion(glyphLocation.width, glyphLocation.height);
		}
	}

	FT_Done_Face(face);
	FT_Done_FreeType(library);
}

GlyphLocation TextureFont::_getGlyphLocation(FT_Library library, FT_Face face)
{
	GlyphLocation glyphLocation;
	FT_Bitmap bitmap;
	int depth = _atlas->getDepth();
	if (_outlineType == 0)
	{
		FT_GlyphSlot slot = face->glyph;
		bitmap = slot->bitmap;
		glyphLocation.top = slot->bitmap_top;
		glyphLocation.left = slot->bitmap_left;
	}
	else
	{
		FT_Stroker stroker;
		FT_BitmapGlyph bitmapGlyph;

		FT_Error error = FT_Stroker_New(library, &stroker);
		if (error) { throw new std::exception(); }

		FT_Stroker_Set(stroker, static_cast<int>(_outlineThickness * POINT_RES),
			FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);

		FT_Glyph glyph;
		error = FT_Get_Glyph(face->glyph, &glyph);
		if (error) { throw new std::exception(); }

		if (_outlineType == 1)
		{
			error = FT_Glyph_Stroke(&glyph, stroker, 1);
		}
		else if (_outlineType == 2)
		{
			error = FT_Glyph_StrokeBorder(&glyph, stroker, 0, 1);
		}
		else if (_outlineType == 3)
		{
			error = FT_Glyph_StrokeBorder(&glyph, stroker, 1, 1);
		}

		if (error) { throw new std::exception(); }

		FT_Render_Mode renderMode = _atlas->getDepth() == 1 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_LCD;
		error = FT_Glyph_To_Bitmap(&glyph, renderMode, 0, 1);
		if (error) { throw new std::exception(); }

		bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(glyph);
		bitmap = bitmapGlyph->bitmap;
		glyphLocation.left = bitmapGlyph->left;
		glyphLocation.top = bitmapGlyph->top;
		FT_Stroker_Done(stroker);
	}

	glyphLocation.width = bitmap.width / depth;
	glyphLocation.height = bitmap.rows;

	return glyphLocation;
}

void TextureFont::_setFiltering(FT_Library library)
{
	if (_atlas->getDepth() == 3)
	{
		FT_Library_SetLcdFilter(library, FT_LCD_FILTER_LIGHT);
		if (_filtering)
		{
			FT_Library_SetLcdFilterWeights(library, _lcdWeights);
		}
	}
}

FT_Int32 TextureFont::_getFlags()
{
	FT_Int32 flags = 0;
	if (_outlineType > 0)
	{
		flags |= FT_LOAD_NO_BITMAP;
	}
	else
	{
		flags |= FT_LOAD_RENDER;
	}

	if (!_hinting)
	{
		flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
	}
	else
	{
		flags |= FT_LOAD_FORCE_AUTOHINT;
	}

	if (_atlas->getDepth() == 3)
	{
		flags |= FT_LOAD_TARGET_LCD;
	}

	return flags;
}

bool TextureFont::_shouldLoadGlyph(const char charCode)
{
	// Skip glyphs that have already been loaded
	bool skip = false;
	int sizeGlyphs = static_cast<int>(_glyphs.size());
	for (int j = 0; j < sizeGlyphs; ++j)
	{
		auto glyph = _glyphs[j];
		if (glyph->charCode == charCode &&
			(glyph->outlineType == _outlineType && glyph->outlineThickness == _outlineThickness))
		{
			skip = true;
			break;
		}
	}

	return skip;
}

void TextureFont::_initialize()
{
	FT_Library library;
	FT_Face face;
	FT_Size_Metrics metrics;

	FT_Error error = FT_Init_FreeType(&library);
	if (error != FT_Err_Ok) { throw new std::exception(); }

	_loadFace(library, &face, _pointSize * 100.0f);
	metrics = face->size->metrics;
	_ascender = (metrics.ascender >> 6) / 100.0f;
	_descender = (metrics.descender >> 6) / 100.0f;
	_height = (metrics.height >> 6) / 100.0f;
	_linegap = _height - _ascender + _descender;

	FT_Done_Face(face);
	FT_Done_FreeType(library);
}

void TextureFont::_loadFace(FT_Library library, FT_Face *face, float pointSize)
{
	FT_Error error = FT_New_Face(library, _filename.c_str(), 0, face);
	if (error != FT_Err_Ok)
	{
		throw new std::exception();
	}

	error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
	if (error)
	{
		throw new std::exception();
	}

	error = FT_Set_Char_Size(*face, (int)(pointSize * POINT_RES), 0, DPI * POINT_RES, DPI);
	if (error)
	{
		throw new std::exception();
	}

	FT_Matrix matrix = {
		(int)((1.0 / POINT_RES) * 0x10000L),
		0,
		0,
		0x10000L
	};

	FT_Set_Transform(*face, &matrix, nullptr);
}

void TextureFont::_loadFace(FT_Library library, FT_Face *face)
{
	_loadFace(library, face, _pointSize);
}<commit_msg>Remove some space<commit_after>#include "TextureFont.hpp"
#include FT_LCD_FILTER_H
#include FT_STROKER_H

using namespace rffalcon;

#define POINT_RES 64
#define DPI 72

TextureFont::TextureFont(std::shared_ptr<TextureAtlas> atlas, const float pointSize, const std::string &filename)
	: _atlas(atlas), _pointSize(pointSize), _filename(filename)
{
	_lcdWeights[0] = 0x10;
	_lcdWeights[0] = 0x40;
	_lcdWeights[0] = 0x70;
	_lcdWeights[0] = 0x40;
	_lcdWeights[0] = 0x10;
	_initialize();
}

TextureFont::~TextureFont()
{
}

float TextureFont::getHeight() const
{
	return _height;
}

void TextureFont::loadGlyphs(const std::string &text)
{
	int width = _atlas->getWidth();
	int height = _atlas->getHeight();
	int depth = _atlas->getDepth();

	FT_Library library;
	FT_Face face;
	FT_Error error = FT_Init_FreeType(&library);
	if (error != FT_Err_Ok) { throw new std::exception(); }

	_loadFace(library, &face);

	FT_Int32 flags = _getFlags();
	int length = text.length();
	// Load the glyph for each character in the string
	for (int i = 0; i < length; ++i)
	{
		char charCode = text[i];
		if (_shouldLoadGlyph(charCode))
		{
			_setFiltering(library);
			FT_UInt glyphIndex = FT_Get_Char_Index(face, charCode);
			error = FT_Load_Glyph(face, glyphIndex, flags);
			if (error) { throw new std::exception(); }
			GlyphLocation glyphLocation = _getGlyphLocation(library, face);
			s1::ivec4 region = _atlas->getRegion(glyphLocation.width, glyphLocation.height);
		}
	}

	FT_Done_Face(face);
	FT_Done_FreeType(library);
}

GlyphLocation TextureFont::_getGlyphLocation(FT_Library library, FT_Face face)
{
	GlyphLocation glyphLocation;
	FT_Bitmap bitmap;
	int depth = _atlas->getDepth();
	if (_outlineType == 0)
	{
		FT_GlyphSlot slot = face->glyph;
		bitmap = slot->bitmap;
		glyphLocation.top = slot->bitmap_top;
		glyphLocation.left = slot->bitmap_left;
	}
	else
	{
		FT_Stroker stroker;
		FT_BitmapGlyph bitmapGlyph;

		FT_Error error = FT_Stroker_New(library, &stroker);
		if (error) { throw new std::exception(); }

		FT_Stroker_Set(stroker, static_cast<int>(_outlineThickness * POINT_RES),
			FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);

		FT_Glyph glyph;
		error = FT_Get_Glyph(face->glyph, &glyph);
		if (error) { throw new std::exception(); }

		if (_outlineType == 1)
		{
			error = FT_Glyph_Stroke(&glyph, stroker, 1);
		}
		else if (_outlineType == 2)
		{
			error = FT_Glyph_StrokeBorder(&glyph, stroker, 0, 1);
		}
		else if (_outlineType == 3)
		{
			error = FT_Glyph_StrokeBorder(&glyph, stroker, 1, 1);
		}

		if (error) { throw new std::exception(); }

		FT_Render_Mode renderMode = _atlas->getDepth() == 1 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_LCD;
		error = FT_Glyph_To_Bitmap(&glyph, renderMode, 0, 1);
		if (error) { throw new std::exception(); }

		bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(glyph);
		bitmap = bitmapGlyph->bitmap;
		glyphLocation.left = bitmapGlyph->left;
		glyphLocation.top = bitmapGlyph->top;
		FT_Stroker_Done(stroker);
	}

	glyphLocation.width = bitmap.width / depth;
	glyphLocation.height = bitmap.rows;

	return glyphLocation;
}

void TextureFont::_setFiltering(FT_Library library)
{
	if (_atlas->getDepth() == 3)
	{
		FT_Library_SetLcdFilter(library, FT_LCD_FILTER_LIGHT);
		if (_filtering)
		{
			FT_Library_SetLcdFilterWeights(library, _lcdWeights);
		}
	}
}

FT_Int32 TextureFont::_getFlags()
{
	FT_Int32 flags = 0;
	if (_outlineType > 0)
	{
		flags |= FT_LOAD_NO_BITMAP;
	}
	else
	{
		flags |= FT_LOAD_RENDER;
	}

	if (!_hinting)
	{
		flags |= FT_LOAD_NO_HINTING | FT_LOAD_NO_AUTOHINT;
	}
	else
	{
		flags |= FT_LOAD_FORCE_AUTOHINT;
	}

	if (_atlas->getDepth() == 3)
	{
		flags |= FT_LOAD_TARGET_LCD;
	}

	return flags;
}

bool TextureFont::_shouldLoadGlyph(const char charCode)
{
	// Skip glyphs that have already been loaded
	bool skip = false;
	int sizeGlyphs = static_cast<int>(_glyphs.size());
	for (int j = 0; j < sizeGlyphs; ++j)
	{
		auto glyph = _glyphs[j];
		if (glyph->charCode == charCode &&
			(glyph->outlineType == _outlineType && glyph->outlineThickness == _outlineThickness))
		{
			skip = true;
			break;
		}
	}

	return skip;
}

void TextureFont::_initialize()
{
	FT_Library library;
	FT_Face face;
	FT_Size_Metrics metrics;

	FT_Error error = FT_Init_FreeType(&library);
	if (error != FT_Err_Ok) { throw new std::exception(); }

	_loadFace(library, &face, _pointSize * 100.0f);
	metrics = face->size->metrics;
	_ascender = (metrics.ascender >> 6) / 100.0f;
	_descender = (metrics.descender >> 6) / 100.0f;
	_height = (metrics.height >> 6) / 100.0f;
	_linegap = _height - _ascender + _descender;

	FT_Done_Face(face);
	FT_Done_FreeType(library);
}

void TextureFont::_loadFace(FT_Library library, FT_Face *face, float pointSize)
{
	FT_Error error = FT_New_Face(library, _filename.c_str(), 0, face);
	if (error != FT_Err_Ok)
	{
		throw new std::exception();
	}

	error = FT_Select_Charmap(*face, FT_ENCODING_UNICODE);
	if (error)
	{
		throw new std::exception();
	}

	error = FT_Set_Char_Size(*face, (int)(pointSize * POINT_RES), 0, DPI * POINT_RES, DPI);
	if (error)
	{
		throw new std::exception();
	}

	FT_Matrix matrix = {
		(int)((1.0 / POINT_RES) * 0x10000L),
		0,
		0,
		0x10000L
	};

	FT_Set_Transform(*face, &matrix, nullptr);
}

void TextureFont::_loadFace(FT_Library library, FT_Face *face)
{
	_loadFace(library, face, _pointSize);
}<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/mc/perf_reg.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file perf_reg.C
/// @brief Subroutines to manipulate the memory controller performance registers
///
// *HWP HWP Owner: Brian Silver <bsilver@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>

#include <lib/mss_attribute_accessors.H>
#include <lib/shared/mss_const.H>
#include <lib/mc/mc.H>
#include <generic/memory/lib/utils/scom.H>
#include <lib/dimm/kind.H>
#include <generic/memory/lib/utils/find.H>

using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;

namespace mss
{

namespace mc
{

///
/// @brief Perform initializations of the MC performance registers
/// @note Some of these bits are taken care of in the scom initfiles
/// @param[in] i_target the target which has the MCA to map
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode setup_perf2_register(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    fapi2::buffer<uint64_t> l_data;

    // Get the values we need to put in the register
    uint64_t l_value;
    FAPI_TRY( calculate_perf2(i_target, l_value) );

    // Setup the registers
    FAPI_TRY( mss::getScom(i_target, MCS_0_PORT02_MCPERF2, l_data) );

    // Per S. Powell 7/16, setup these registers but don't enable the function yet. So enable bits are
    // intentionally not set
    l_data.insertFromRight<MCS_PORT02_MCPERF2_REFRESH_BLOCK_CONFIG,
                           MCS_PORT02_MCPERF2_REFRESH_BLOCK_CONFIG_LEN>(l_value);

    FAPI_TRY( mss::putScom(i_target, MCS_0_PORT02_MCPERF2, l_data) );

fapi_try_exit:
    return fapi2::FAPI2_RC_SUCCESS;
}

///
/// @brief Calculate the value of the MC perf2 register.
/// @param[in] i_target the target which has the MCA to map
/// @param[out] o_value the perf2 value for the MCA
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode calculate_perf2(const fapi2::Target<TARGET_TYPE_MCA>& i_target, uint64_t& o_value)
{
    //
    // From Senor Powell 7/16
    // if (slots=1, masters=1)
    //   MCPERF2_Refresh_Block_Config=0b000
    // if (slots=1, masters=2)
    //   MCPERF2_Refresh_Block_Config=0b001
    // if (slots=1, masters=4)
    //  MCPERF2_Refresh_Block_Config=0b100
    // if (slots=2, masters=1)
    //  MCPERF2_Refresh_Block_Config=0b010
    // if (slots=2, masters=2)
    //  MCPERF2_Refresh_Block_Config=0b011
    // if (slots=2, masters=4)
    //  MCPERF2_Refresh_Block_Config=0b100
    //
    // if slot0 is 2 masters and slot1 is 1 master, just choose the 2 slot, 2 masters setting.
    // (i.e., choose the max(mranks_dimm1, mranks_dimm2)

    constexpr uint64_t l_refresh_values[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] =
    {
        {0b000, 0b001, 0, 0b100}, // Skip the ol' 3 rank DIMM
        {0b010, 0b011, 0, 0b100}
    };

    FAPI_INF("Calculating perf2 register for MCA%d (%d)", mss::pos(i_target), mss::index(i_target));

    // Find the DIMM on this port with the most master ranks.
    // That's how we know which element in the table to use.
    // uint8_t so I can use it to read from an attribute directly

    uint8_t l_mrank_index = 0;
    uint8_t l_master_ranks_zero = 0;
    uint8_t l_master_ranks_one = 0;

    fapi2::buffer<uint64_t> l_data;

    const auto l_dimm = mss::find_targets<TARGET_TYPE_DIMM>(i_target);
    const auto l_slot_index = l_dimm.size() - 1;

    switch(l_dimm.size())
    {
        // No DIMM, nothing to do
        case 0:
            return fapi2::FAPI2_RC_SUCCESS;
            break;

        // One DIMM, we've got the slots of fun
        case 1:
            FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[0], l_mrank_index) );
            --l_mrank_index;
            FAPI_INF("1 DIMM mranks: D0[%d] index %d", l_mrank_index + 1, l_mrank_index);
            break;

        // Two DIMM, find the max of the master ranks
        case 2:
            {
                FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[0], l_master_ranks_zero) );
                FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[1], l_master_ranks_one) );

                l_mrank_index = std::max(l_master_ranks_zero, l_master_ranks_one) - 1;
                FAPI_INF("2 DIMM mranks: D0[%d] D1[%d] index %d", l_master_ranks_zero, l_master_ranks_one, l_mrank_index);
            }
            break;

        default:
            // We have a bug - no way to get more than 2 DIMM in a dual-drop system
            FAPI_ERR("seeing %d DIMM on %s", l_dimm.size(), mss::c_str(i_target));
            fapi2::Assert(false);
            break;
    };

    FAPI_INF("Refresh Block Config: %u ([%d][%d] populated slots: %d, max mranks: %d)",
             l_refresh_values[l_slot_index][l_mrank_index],
             l_slot_index, l_mrank_index,
             l_slot_index + 1, l_mrank_index + 1);

    o_value = l_refresh_values[l_slot_index][l_mrank_index];

fapi_try_exit:
    return fapi2::current_err;
}

} // namespace

} // namespace
<commit_msg>Update HPW Level for MSS API library<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/mc/perf_reg.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file perf_reg.C
/// @brief Subroutines to manipulate the memory controller performance registers
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB

#include <fapi2.H>

#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>

#include <lib/mss_attribute_accessors.H>
#include <lib/shared/mss_const.H>
#include <lib/mc/mc.H>
#include <generic/memory/lib/utils/scom.H>
#include <lib/dimm/kind.H>
#include <generic/memory/lib/utils/find.H>

using fapi2::TARGET_TYPE_MCA;
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_DIMM;

namespace mss
{

namespace mc
{

///
/// @brief Perform initializations of the MC performance registers
/// @note Some of these bits are taken care of in the scom initfiles
/// @param[in] i_target the target which has the MCA to map
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode setup_perf2_register(const fapi2::Target<TARGET_TYPE_MCA>& i_target)
{
    fapi2::buffer<uint64_t> l_data;

    // Get the values we need to put in the register
    uint64_t l_value;
    FAPI_TRY( calculate_perf2(i_target, l_value) );

    // Setup the registers
    FAPI_TRY( mss::getScom(i_target, MCS_0_PORT02_MCPERF2, l_data) );

    // Per S. Powell 7/16, setup these registers but don't enable the function yet. So enable bits are
    // intentionally not set
    l_data.insertFromRight<MCS_PORT02_MCPERF2_REFRESH_BLOCK_CONFIG,
                           MCS_PORT02_MCPERF2_REFRESH_BLOCK_CONFIG_LEN>(l_value);

    FAPI_TRY( mss::putScom(i_target, MCS_0_PORT02_MCPERF2, l_data) );

fapi_try_exit:
    return fapi2::FAPI2_RC_SUCCESS;
}

///
/// @brief Calculate the value of the MC perf2 register.
/// @param[in] i_target the target which has the MCA to map
/// @param[out] o_value the perf2 value for the MCA
/// @return FAPI2_RC_SUCCESS iff ok
///
fapi2::ReturnCode calculate_perf2(const fapi2::Target<TARGET_TYPE_MCA>& i_target, uint64_t& o_value)
{
    //
    // From Senor Powell 7/16
    // if (slots=1, masters=1)
    //   MCPERF2_Refresh_Block_Config=0b000
    // if (slots=1, masters=2)
    //   MCPERF2_Refresh_Block_Config=0b001
    // if (slots=1, masters=4)
    //  MCPERF2_Refresh_Block_Config=0b100
    // if (slots=2, masters=1)
    //  MCPERF2_Refresh_Block_Config=0b010
    // if (slots=2, masters=2)
    //  MCPERF2_Refresh_Block_Config=0b011
    // if (slots=2, masters=4)
    //  MCPERF2_Refresh_Block_Config=0b100
    //
    // if slot0 is 2 masters and slot1 is 1 master, just choose the 2 slot, 2 masters setting.
    // (i.e., choose the max(mranks_dimm1, mranks_dimm2)

    constexpr uint64_t l_refresh_values[MAX_DIMM_PER_PORT][MAX_RANK_PER_DIMM] =
    {
        {0b000, 0b001, 0, 0b100}, // Skip the ol' 3 rank DIMM
        {0b010, 0b011, 0, 0b100}
    };

    FAPI_INF("Calculating perf2 register for MCA%d (%d)", mss::pos(i_target), mss::index(i_target));

    // Find the DIMM on this port with the most master ranks.
    // That's how we know which element in the table to use.
    // uint8_t so I can use it to read from an attribute directly

    uint8_t l_mrank_index = 0;
    uint8_t l_master_ranks_zero = 0;
    uint8_t l_master_ranks_one = 0;

    fapi2::buffer<uint64_t> l_data;

    const auto l_dimm = mss::find_targets<TARGET_TYPE_DIMM>(i_target);
    const auto l_slot_index = l_dimm.size() - 1;

    switch(l_dimm.size())
    {
        // No DIMM, nothing to do
        case 0:
            return fapi2::FAPI2_RC_SUCCESS;
            break;

        // One DIMM, we've got the slots of fun
        case 1:
            FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[0], l_mrank_index) );
            --l_mrank_index;
            FAPI_INF("1 DIMM mranks: D0[%d] index %d", l_mrank_index + 1, l_mrank_index);
            break;

        // Two DIMM, find the max of the master ranks
        case 2:
            {
                FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[0], l_master_ranks_zero) );
                FAPI_TRY( mss::eff_num_master_ranks_per_dimm(l_dimm[1], l_master_ranks_one) );

                l_mrank_index = std::max(l_master_ranks_zero, l_master_ranks_one) - 1;
                FAPI_INF("2 DIMM mranks: D0[%d] D1[%d] index %d", l_master_ranks_zero, l_master_ranks_one, l_mrank_index);
            }
            break;

        default:
            // We have a bug - no way to get more than 2 DIMM in a dual-drop system
            FAPI_ERR("seeing %d DIMM on %s", l_dimm.size(), mss::c_str(i_target));
            fapi2::Assert(false);
            break;
    };

    FAPI_INF("Refresh Block Config: %u ([%d][%d] populated slots: %d, max mranks: %d)",
             l_refresh_values[l_slot_index][l_mrank_index],
             l_slot_index, l_mrank_index,
             l_slot_index + 1, l_mrank_index + 1);

    o_value = l_refresh_values[l_slot_index][l_mrank_index];

fapi_try_exit:
    return fapi2::current_err;
}

} // namespace

} // namespace
<|endoftext|>


<commit_before>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * span.cpp
 * - Spans and error handling
 */
#include <functional>
#include <iostream>
#include <span.hpp>
#include <parse/lex.hpp>
#include <common.hpp>

Span::Span(const Span& x):
    outer_span(x.outer_span),
    filename(x.filename),
    start_line(x.start_line),
    start_ofs(x.start_ofs),
    end_line(x.end_line),
    end_ofs(x.end_ofs)
{
}
Span::Span(const Position& pos):
    outer_span(),
    filename(pos.filename),
    start_line(pos.line),
    start_ofs(pos.ofs),
    end_line(pos.line),
    end_ofs(pos.ofs)
{
}
Span::Span():
    outer_span(),
    filename("")/*,
    start_line(0), start_ofs(0),
    end_line(0), end_ofs(0) // */
{
    DEBUG("Empty span");
    //filename = FMT(":" << __builtin_return_address(0));
}

void Span::bug(::std::function<void(::std::ostream&)> msg) const
{
    ::std::cerr << this->filename << ":" << this->start_line << ": BUG:";
    msg(::std::cerr);
    ::std::cerr << ::std::endl;
    abort();
}

void Span::error(ErrorType tag, ::std::function<void(::std::ostream&)> msg) const {
    ::std::cerr << this->filename << ":" << this->start_line << ": error:" << tag <<":";
    msg(::std::cerr);
    ::std::cerr << ::std::endl;
    abort();
}
void Span::warning(WarningType tag, ::std::function<void(::std::ostream&)> msg) const {
    ::std::cerr << this->filename << ":" << this->start_line << ": warning:" << tag << ":";
    msg(::std::cerr);
    ::std::cerr << ::std::endl;
    //abort();
}
void Span::note(::std::function<void(::std::ostream&)> msg) const {
    ::std::cerr << this->filename << ":" << this->start_line << ": note:";
    msg(::std::cerr);
    ::std::cerr << ::std::endl;
    //abort();
}

::std::ostream& operator<<(::std::ostream& os, const Span& sp)
{
    os << sp.filename << ":" << sp.start_line;
    return os;
}
<commit_msg>Span - Tweak printing to print context (doesn't apply yet, because nothing provides context)<commit_after>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * span.cpp
 * - Spans and error handling
 */
#include <functional>
#include <iostream>
#include <span.hpp>
#include <parse/lex.hpp>
#include <common.hpp>

Span::Span(const Span& x):
    outer_span(x.outer_span),
    filename(x.filename),
    start_line(x.start_line),
    start_ofs(x.start_ofs),
    end_line(x.end_line),
    end_ofs(x.end_ofs)
{
}
Span::Span(const Position& pos):
    outer_span(),
    filename(pos.filename),
    start_line(pos.line),
    start_ofs(pos.ofs),
    end_line(pos.line),
    end_ofs(pos.ofs)
{
}
Span::Span():
    outer_span(),
    filename("")/*,
    start_line(0), start_ofs(0),
    end_line(0), end_ofs(0) // */
{
    DEBUG("Empty span");
    //filename = FMT(":" << __builtin_return_address(0));
}

namespace {
    void print_span_message(const Span& sp, ::std::function<void(::std::ostream&)> tag, ::std::function<void(::std::ostream&)> msg)
    {
        auto& sink = ::std::cerr;
        sink << sp.filename << ":" << sp.start_line << ": ";
        tag(sink);
        sink << ":";
        msg(sink);
        sink << ::std::endl;
        const auto* parent = sp.outer_span.get();
        while(parent)
        {
            sink << parent->filename << ":" << parent->start_line << ": note: From here" << ::std::endl;
            parent = parent->outer_span.get();
        }
    }
}
void Span::bug(::std::function<void(::std::ostream&)> msg) const
{
    print_span_message(*this, [](auto& os){os << "BUG";}, msg);
    abort();
}

void Span::error(ErrorType tag, ::std::function<void(::std::ostream&)> msg) const {
    print_span_message(*this, [&](auto& os){os << "error:" << tag;}, msg);
    abort();
}
void Span::warning(WarningType tag, ::std::function<void(::std::ostream&)> msg) const {
    print_span_message(*this, [&](auto& os){os << "warning" << tag;}, msg);
}
void Span::note(::std::function<void(::std::ostream&)> msg) const {
    print_span_message(*this, [](auto& os){os << "note";}, msg);
}

::std::ostream& operator<<(::std::ostream& os, const Span& sp)
{
    os << sp.filename << ":" << sp.start_line;
    return os;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_extract_sbe_rc.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_extract_sbe_rc.H
///
/// @brief Check for errors on the PNOR , SEEPROM
//------------------------------------------------------------------------------
// *HWP HW Owner        : Soma BhanuTej <soma.bhanu@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Sunil Kumar <skumar8j@in.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : FSP:HB
//------------------------------------------------------------------------------

#ifndef _P9_EXTRACT_SBE_RC_H_
#define _P9_EXTRACT_SBE_RC_H_

#include <fapi2.H>

typedef fapi2::ReturnCode (*p9_extract_sbe_rc_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief called on all chips(master and slaves) to look for any correctable errors on the PNOR and/or SEEPROM, the soft_error flag tells the procedure not to generate error if no HW issue.
///
/// @param[in]     i_target_chiplet   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_extract_sbe_rc(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<commit_msg>Level 2 HWP for p9_extract_sbe_rc - Ver2<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_extract_sbe_rc.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_extract_sbe_rc.H
///
/// @brief Check for errors on the SBE, OTPROM, PIBMEM & SEEPROM
//------------------------------------------------------------------------------
// *HWP HW Owner        : Soma BhanuTej <soma.bhanu@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Sunil Kumar <skumar8j@in.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : FSP:HB
//------------------------------------------------------------------------------

#ifndef _P9_EXTRACT_SBE_RC_H_
#define _P9_EXTRACT_SBE_RC_H_

#include <fapi2.H>

namespace P9_EXTRACT_SBE_RC
{
enum RETURN_ACTION
{
    RESTART_SBE       = 1, // Trigger external HRESET to reset SBE
    RESTART_CBS       = 2, // Trigger Warm ipl where we don't switch off VSB just toggle start_cbs from FSP
    REIPL_BKP_SEEPROM = 3, // Run IPL by selecting backup seeprom
    RE_IPL            = 4, // Reload/update of SEEPROM required or deconfig the chip
    NO_RECOVERY_ACTION = 5 // No recovery action possible to correct this error, Replace the chip with new one
};
};

typedef fapi2::ReturnCode (*p9_extract_sbe_rc_FP_t)(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&,
        P9_EXTRACT_SBE_RC::RETURN_ACTION&);

/// @brief called on all chips(master and slaves) to look for any correctable errors on the SBE, OTPROM, PIBMEM & SEEPROM, the soft_error flag tells the procedure not to generate error if no HW issue.
///
/// @param[in]     i_target_chiplet   Reference to TARGET_TYPE_PROC_CHIP target
/// @param[out]    o_return_action    Returns the action to be taken on an error
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_extract_sbe_rc(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip,
                                        P9_EXTRACT_SBE_RC::RETURN_ACTION& o_return_action);
}

#endif
<|endoftext|>


<commit_before>#ifndef regex_hh_INCLUDED
#define regex_hh_INCLUDED

#include "string.hh"
#include "regex_impl.hh"

namespace Kakoune
{

// Regex that keeps track of its string representation
class Regex
{
public:
    Regex() = default;

    explicit Regex(StringView re, RegexCompileFlags flags = RegexCompileFlags::None);
    bool empty() const { return m_str.empty(); }
    bool operator==(const Regex& other) const { return m_str == other.m_str; }
    bool operator!=(const Regex& other) const { return m_str != other.m_str; }

    const String& str() const { return m_str; }

    size_t mark_count() const { return m_impl->save_count / 2 - 1; }

    static constexpr const char* option_type_name = "regex";

    const CompiledRegex* impl() const { return m_impl.get(); }

private:
    RefPtr<CompiledRegex> m_impl;
    String m_str;
};

template<typename Iterator>
struct MatchResults
{
    struct SubMatch : std::pair<Iterator, Iterator>
    {
        SubMatch() = default;
        SubMatch(Iterator begin, Iterator end)
            : std::pair<Iterator, Iterator>{begin, end}, matched{begin != Iterator{}}
        {}

        bool matched = false;
    };

    struct iterator : std::iterator<std::bidirectional_iterator_tag, SubMatch, size_t, SubMatch*, SubMatch>
    {
        using It = typename Vector<Iterator, MemoryDomain::Regex>::const_iterator;

        iterator() = default;
        iterator(It it) : m_it{std::move(it)} {}

        iterator& operator--() { m_it += 2; return *this; }
        iterator& operator++() { m_it += 2; return *this; }
        SubMatch operator*() const { return {*m_it, *(m_it+1)}; }

        friend bool operator==(const iterator& lhs, const iterator& rhs) { return lhs.m_it == rhs.m_it; }
        friend bool operator!=(const iterator& lhs, const iterator& rhs) { return lhs.m_it != rhs.m_it; }
    private:

        It m_it;
    };

    MatchResults() = default;
    MatchResults(Vector<Iterator, MemoryDomain::Regex> values) : m_values{std::move(values)} {}

    iterator begin() const { return iterator{m_values.begin()}; }
    iterator cbegin() const { return iterator{m_values.cbegin()}; }
    iterator end() const { return iterator{m_values.end()}; }
    iterator cend() const { return iterator{m_values.cend()}; }

    size_t size() const { return m_values.size() / 2; }
    bool empty() const { return m_values.empty(); }

    SubMatch operator[](size_t i) const
    {
        return i * 2 < m_values.size() ?
            SubMatch{m_values[i*2], m_values[i*2+1]} : SubMatch{};
    }

    friend bool operator==(const MatchResults& lhs, const MatchResults& rhs)
    {
        return lhs.m_values == rhs.m_values;
    }

    friend bool operator!=(const MatchResults& lhs, const MatchResults& rhs)
    {
        return not (lhs == rhs);
    }

    void swap(MatchResults& other)
    {
        m_values.swap(other.m_values);
    }

    Vector<Iterator, MemoryDomain::Regex>& values() { return m_values; }

private:
    Vector<Iterator, MemoryDomain::Regex> m_values;
};

inline RegexExecFlags match_flags(bool bol, bool eol, bool bow, bool eow)
{
    return (bol ? RegexExecFlags::None : RegexExecFlags::NotBeginOfLine) |
           (eol ? RegexExecFlags::None : RegexExecFlags::NotEndOfLine) |
           (bow ? RegexExecFlags::None : RegexExecFlags::NotBeginOfWord) |
           (eow ? RegexExecFlags::None : RegexExecFlags::NotEndOfWord);
}

template<typename It>
bool regex_match(It begin, It end, const Regex& re)
{
    ThreadedRegexVM<It, MatchDirection::Forward> vm{*re.impl()};
    return vm.exec(begin, end, begin, end, RegexExecFlags::AnyMatch | RegexExecFlags::NoSaves);
}

template<typename It>
bool regex_match(It begin, It end, MatchResults<It>& res, const Regex& re)
{
    res.values().clear();
    ThreadedRegexVM<It, MatchDirection::Forward> vm{*re.impl()};
    if (vm.exec(begin, end, begin, end, RegexExecFlags::None))
    {
        std::copy(vm.captures().begin(), vm.captures().end(), std::back_inserter(res.values()));
        return true;
    }
    return false;
}

template<typename It>
bool regex_search(It begin, It end, It subject_begin, It subject_end, const Regex& re,
                  RegexExecFlags flags = RegexExecFlags::None)
{
    ThreadedRegexVM<It, MatchDirection::Forward> vm{*re.impl()};
    return vm.exec(begin, end, subject_begin, subject_end,
                   flags | RegexExecFlags::Search | RegexExecFlags::AnyMatch | RegexExecFlags::NoSaves);
}

template<typename It, MatchDirection direction = MatchDirection::Forward>
bool regex_search(It begin, It end, It subject_begin, It subject_end,
                  MatchResults<It>& res, const Regex& re,
                  RegexExecFlags flags = RegexExecFlags::None)
{
    res.values().clear();
    ThreadedRegexVM<It, direction> vm{*re.impl()};
    if (vm.exec(begin, end, subject_begin, subject_end, flags | RegexExecFlags::Search))
    {
        std::move(vm.captures().begin(), vm.captures().end(), std::back_inserter(res.values()));
        return true;
    }
    return false;
}

template<typename It>
bool backward_regex_search(It begin, It end, It subject_begin, It subject_end,
                           MatchResults<It>& res, const Regex& re,
                           RegexExecFlags flags = RegexExecFlags::None)
{
    return regex_search<It, MatchDirection::Backward>(begin, end, subject_begin, subject_end, res, re, flags);
}

String option_to_string(const Regex& re);
void option_from_string(StringView str, Regex& re);

template<typename Iterator, MatchDirection direction = MatchDirection::Forward>
struct RegexIterator
{
    using ValueType = MatchResults<Iterator>;

    RegexIterator() = default;
    RegexIterator(Iterator begin, Iterator end,
                  Iterator subject_begin, Iterator subject_end,
                  const Regex& re,
                  RegexExecFlags flags = RegexExecFlags::None)
        : m_regex{&re}, m_next_pos{direction == MatchDirection::Forward ? begin : end},
          m_begin{begin}, m_end{end},
          m_subject_begin{subject_begin}, m_subject_end{subject_end},
          m_flags{flags}
    {
        next();
    }

    RegexIterator(Iterator begin, Iterator end, const Regex& re,
                  RegexExecFlags flags = RegexExecFlags::None)
        : RegexIterator{begin, end, begin, end, re, flags} {}

    const ValueType& operator*() const { kak_assert(m_regex); return m_results; }
    const ValueType* operator->() const { kak_assert(m_regex); return &m_results; }

    RegexIterator& operator++()
    {
        next();
        return *this;
    }

    friend bool operator==(const RegexIterator& lhs, const RegexIterator& rhs)
    {
        if (lhs.m_regex == nullptr and rhs.m_regex == nullptr)
            return true;

        return lhs.m_regex == rhs.m_regex and
               lhs.m_next_pos == rhs.m_next_pos and
               lhs.m_end == rhs.m_end and
               lhs.m_flags == rhs.m_flags and
               lhs.m_results == rhs.m_results;
    }

    friend bool operator!=(const RegexIterator& lhs, const RegexIterator& rhs)
    {
        return not (lhs == rhs);
    }

    RegexIterator begin() { return *this; }
    RegexIterator end() { return {}; }

private:
    void next()
    {
        kak_assert(m_regex);

        RegexExecFlags additional_flags{};
        if (m_results.size() and m_results[0].first == m_results[0].second)
            additional_flags |= RegexExecFlags::NotInitialNull;

        if (direction == MatchDirection::Forward)
        {
            if (not regex_search(m_next_pos, m_end, m_subject_begin, m_subject_end,
                                 m_results, *m_regex, m_flags | additional_flags))
                m_regex = nullptr;
            else
                m_next_pos = m_results[0].second;
        }
        else
        {
            if (not backward_regex_search(m_begin, m_next_pos, m_subject_begin, m_subject_end,
                                          m_results, *m_regex, m_flags | additional_flags))
                m_regex = nullptr;
            else
                m_next_pos = m_results[0].first;
        }
    }

    const Regex* m_regex = nullptr;
    MatchResults<Iterator> m_results;
    Iterator m_next_pos{};
    const Iterator m_begin{};
    const Iterator m_end{};
    const Iterator m_subject_begin{};
    const Iterator m_subject_end{};
    const RegexExecFlags m_flags = RegexExecFlags::None;
};

}

#endif // regex_hh_INCLUDED
<commit_msg>Refactor RegexIterator::next to directly use a ThreadedRegexVM<commit_after>#ifndef regex_hh_INCLUDED
#define regex_hh_INCLUDED

#include "string.hh"
#include "regex_impl.hh"

namespace Kakoune
{

// Regex that keeps track of its string representation
class Regex
{
public:
    Regex() = default;

    explicit Regex(StringView re, RegexCompileFlags flags = RegexCompileFlags::None);
    bool empty() const { return m_str.empty(); }
    bool operator==(const Regex& other) const { return m_str == other.m_str; }
    bool operator!=(const Regex& other) const { return m_str != other.m_str; }

    const String& str() const { return m_str; }

    size_t mark_count() const { return m_impl->save_count / 2 - 1; }

    static constexpr const char* option_type_name = "regex";

    const CompiledRegex* impl() const { return m_impl.get(); }

private:
    RefPtr<CompiledRegex> m_impl;
    String m_str;
};

template<typename Iterator>
struct MatchResults
{
    struct SubMatch : std::pair<Iterator, Iterator>
    {
        SubMatch() = default;
        SubMatch(Iterator begin, Iterator end)
            : std::pair<Iterator, Iterator>{begin, end}, matched{begin != Iterator{}}
        {}

        bool matched = false;
    };

    struct iterator : std::iterator<std::bidirectional_iterator_tag, SubMatch, size_t, SubMatch*, SubMatch>
    {
        using It = typename Vector<Iterator, MemoryDomain::Regex>::const_iterator;

        iterator() = default;
        iterator(It it) : m_it{std::move(it)} {}

        iterator& operator--() { m_it += 2; return *this; }
        iterator& operator++() { m_it += 2; return *this; }
        SubMatch operator*() const { return {*m_it, *(m_it+1)}; }

        friend bool operator==(const iterator& lhs, const iterator& rhs) { return lhs.m_it == rhs.m_it; }
        friend bool operator!=(const iterator& lhs, const iterator& rhs) { return lhs.m_it != rhs.m_it; }
    private:

        It m_it;
    };

    MatchResults() = default;
    MatchResults(Vector<Iterator, MemoryDomain::Regex> values) : m_values{std::move(values)} {}

    iterator begin() const { return iterator{m_values.begin()}; }
    iterator cbegin() const { return iterator{m_values.cbegin()}; }
    iterator end() const { return iterator{m_values.end()}; }
    iterator cend() const { return iterator{m_values.cend()}; }

    size_t size() const { return m_values.size() / 2; }
    bool empty() const { return m_values.empty(); }

    SubMatch operator[](size_t i) const
    {
        return i * 2 < m_values.size() ?
            SubMatch{m_values[i*2], m_values[i*2+1]} : SubMatch{};
    }

    friend bool operator==(const MatchResults& lhs, const MatchResults& rhs)
    {
        return lhs.m_values == rhs.m_values;
    }

    friend bool operator!=(const MatchResults& lhs, const MatchResults& rhs)
    {
        return not (lhs == rhs);
    }

    void swap(MatchResults& other)
    {
        m_values.swap(other.m_values);
    }

    Vector<Iterator, MemoryDomain::Regex>& values() { return m_values; }

private:
    Vector<Iterator, MemoryDomain::Regex> m_values;
};

inline RegexExecFlags match_flags(bool bol, bool eol, bool bow, bool eow)
{
    return (bol ? RegexExecFlags::None : RegexExecFlags::NotBeginOfLine) |
           (eol ? RegexExecFlags::None : RegexExecFlags::NotEndOfLine) |
           (bow ? RegexExecFlags::None : RegexExecFlags::NotBeginOfWord) |
           (eow ? RegexExecFlags::None : RegexExecFlags::NotEndOfWord);
}

template<typename It>
bool regex_match(It begin, It end, const Regex& re)
{
    ThreadedRegexVM<It, MatchDirection::Forward> vm{*re.impl()};
    return vm.exec(begin, end, begin, end, RegexExecFlags::AnyMatch | RegexExecFlags::NoSaves);
}

template<typename It>
bool regex_match(It begin, It end, MatchResults<It>& res, const Regex& re)
{
    res.values().clear();
    ThreadedRegexVM<It, MatchDirection::Forward> vm{*re.impl()};
    if (vm.exec(begin, end, begin, end, RegexExecFlags::None))
    {
        std::copy(vm.captures().begin(), vm.captures().end(), std::back_inserter(res.values()));
        return true;
    }
    return false;
}

template<typename It>
bool regex_search(It begin, It end, It subject_begin, It subject_end, const Regex& re,
                  RegexExecFlags flags = RegexExecFlags::None)
{
    ThreadedRegexVM<It, MatchDirection::Forward> vm{*re.impl()};
    return vm.exec(begin, end, subject_begin, subject_end,
                   flags | RegexExecFlags::Search | RegexExecFlags::AnyMatch | RegexExecFlags::NoSaves);
}

template<typename It, MatchDirection direction = MatchDirection::Forward>
bool regex_search(It begin, It end, It subject_begin, It subject_end,
                  MatchResults<It>& res, const Regex& re,
                  RegexExecFlags flags = RegexExecFlags::None)
{
    res.values().clear();
    ThreadedRegexVM<It, direction> vm{*re.impl()};
    if (vm.exec(begin, end, subject_begin, subject_end, flags | RegexExecFlags::Search))
    {
        std::move(vm.captures().begin(), vm.captures().end(), std::back_inserter(res.values()));
        return true;
    }
    return false;
}

template<typename It>
bool backward_regex_search(It begin, It end, It subject_begin, It subject_end,
                           MatchResults<It>& res, const Regex& re,
                           RegexExecFlags flags = RegexExecFlags::None)
{
    return regex_search<It, MatchDirection::Backward>(begin, end, subject_begin, subject_end, res, re, flags);
}

String option_to_string(const Regex& re);
void option_from_string(StringView str, Regex& re);

template<typename Iterator, MatchDirection direction = MatchDirection::Forward>
struct RegexIterator
{
    using ValueType = MatchResults<Iterator>;

    RegexIterator() = default;
    RegexIterator(Iterator begin, Iterator end,
                  Iterator subject_begin, Iterator subject_end,
                  const Regex& re,
                  RegexExecFlags flags = RegexExecFlags::None)
        : m_program{re.impl()}, m_next_pos{direction == MatchDirection::Forward ? begin : end},
          m_begin{std::move(begin)}, m_end{std::move(end)},
          m_subject_begin{std::move(subject_begin)}, m_subject_end{std::move(subject_end)},
          m_flags{flags}
    {
        next();
    }

    RegexIterator(const Iterator& begin, const Iterator& end, const Regex& re,
                  RegexExecFlags flags = RegexExecFlags::None)
        : RegexIterator{begin, end, begin, end, re, flags} {}

    const ValueType& operator*() const { kak_assert(m_program); return m_results; }
    const ValueType* operator->() const { kak_assert(m_program); return &m_results; }

    RegexIterator& operator++()
    {
        next();
        return *this;
    }

    friend bool operator==(const RegexIterator& lhs, const RegexIterator& rhs)
    {
        if (lhs.m_program == nullptr and rhs.m_program == nullptr)
            return true;

        return lhs.m_program == rhs.m_program and
               lhs.m_next_pos == rhs.m_next_pos and
               lhs.m_end == rhs.m_end and
               lhs.m_flags == rhs.m_flags and
               lhs.m_results == rhs.m_results;
    }

    friend bool operator!=(const RegexIterator& lhs, const RegexIterator& rhs)
    {
        return not (lhs == rhs);
    }

    RegexIterator begin() { return *this; }
    RegexIterator end() { return {}; }

private:
    void next()
    {
        kak_assert(m_program);

        auto additional_flags = RegexExecFlags::Search;
        if (m_results.size() and m_results[0].first == m_results[0].second)
            additional_flags |= RegexExecFlags::NotInitialNull;

        ThreadedRegexVM<Iterator, direction> vm{*m_program};
        constexpr bool forward = direction == MatchDirection::Forward;

        if (vm.exec(forward ? m_next_pos : m_begin, forward ? m_end : m_next_pos,
                    m_subject_begin, m_subject_end, m_flags | additional_flags))
        {
            m_results.values().clear();
            std::move(vm.captures().begin(), vm.captures().end(), std::back_inserter(m_results.values()));
            m_next_pos = (direction == MatchDirection::Forward) ? m_results[0].second : m_results[0].first;
        }
        else
            m_program = nullptr;
    }

    const CompiledRegex* m_program = nullptr;
    MatchResults<Iterator> m_results;
    Iterator m_next_pos{};
    const Iterator m_begin{};
    const Iterator m_end{};
    const Iterator m_subject_begin{};
    const Iterator m_subject_end{};
    const RegexExecFlags m_flags = RegexExecFlags::None;
};

}

#endif // regex_hh_INCLUDED
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// ParserBase.cpp
// Base class for parsing.
//
// File is under the MIT license; see LICENSE for details.
//------------------------------------------------------------------------------
#include "slang/parsing/ParserBase.h"

#include "slang/parsing/Preprocessor.h"
#include "slang/util/BumpAllocator.h"

namespace slang {

ParserBase::ParserBase(Preprocessor& preprocessor) :
    alloc(preprocessor.getAllocator()), window(preprocessor) {
}

void ParserBase::prependSkippedTokens(Token& token) {
    SmallVectorSized<Trivia, 8> buffer;
    buffer.append(Trivia{ TriviaKind::SkippedTokens, skippedTokens.copy(alloc) });
    buffer.appendRange(token.trivia());

    token = token.withTrivia(alloc, buffer.copy(alloc));
    skippedTokens.clear();
}

Diagnostics& ParserBase::getDiagnostics() {
    return window.tokenSource.getDiagnostics();
}

Diagnostic& ParserBase::addDiag(DiagCode code, SourceLocation location) {
    // If we issued this error in response to seeing an EOF token, back up and put
    // the error on the last consumed token instead.
    if (peek(TokenKind::EndOfFile) && peek().location() == location) {
        Token last = getLastConsumed();
        if (last)
            location = last.location() + last.rawText().size();
    }

    return getDiagnostics().add(code, location);
}

Token ParserBase::peek(uint32_t offset) {
    while (window.currentOffset + offset >= window.count)
        window.addNew();
    return window.buffer[window.currentOffset + offset];
}

Token ParserBase::peek() {
    if (!window.currentToken) {
        if (window.currentOffset >= window.count)
            window.addNew();
        window.currentToken = window.buffer[window.currentOffset];
    }
    ASSERT(window.currentToken);
    return window.currentToken;
}

bool ParserBase::peek(TokenKind kind) {
    return peek().kind == kind;
}

Token ParserBase::consume() {
    auto result = peek();
    window.moveToNext();
    if (!skippedTokens.empty())
        prependSkippedTokens(result);
    return result;
}

Token ParserBase::consumeIf(TokenKind kind) {
    if (peek(kind))
        return consume();
    return Token();
}

Token ParserBase::expect(TokenKind kind) {
    // keep this method small so that it gets inlined
    auto result = peek();
    if (result.kind != kind)
        result = Token::createExpected(alloc, getDiagnostics(), result, kind, window.lastConsumed);
    else
        window.moveToNext();

    if (!skippedTokens.empty())
        prependSkippedTokens(result);

    return result;
}

void ParserBase::skipToken(std::optional<DiagCode> diagCode) {
    auto token = peek();
    skippedTokens.append(token);
    window.moveToNext();

    if (diagCode)
        addDiag(*diagCode, token.location()) << token.range();
}

void ParserBase::pushTokens(span<const Token> tokens) {
    window.insertHead(tokens);
}

Token ParserBase::missingToken(TokenKind kind, SourceLocation location) {
    return Token::createMissing(alloc, kind, location);
}

Token ParserBase::getLastConsumed() const {
    return window.lastConsumed;
}

void ParserBase::Window::addNew() {
    if (count >= capacity) {
        // shift tokens to the left if we are too far to the right
        uint32_t shift = count - currentOffset;
        if (currentOffset > (capacity >> 1)) {
            if (shift > 0)
                memmove(buffer, buffer + currentOffset, shift * sizeof(Token));
        }
        else {
            capacity *= 2;
            Token* newBuffer = new Token[capacity];
            memcpy(newBuffer, buffer + currentOffset, shift * sizeof(Token));

            delete[] buffer;
            buffer = newBuffer;
        }

        count -= currentOffset;
        currentOffset = 0;
    }

    buffer[count] = tokenSource.next();
    count++;
}

void ParserBase::Window::moveToNext() {
    lastConsumed = currentToken;
    currentToken = Token();
    currentOffset++;
}

void ParserBase::Window::insertHead(span<const Token> tokens) {
    if (currentOffset >= (uint32_t)tokens.size()) {
        currentOffset -= (uint32_t)tokens.size();
        memcpy(buffer + currentOffset, tokens.data(), tokens.size() * sizeof(Token));
        return;
    }

    uint32_t existing = count - currentOffset;
    ASSERT((uint32_t)tokens.size() + existing < capacity);

    memmove(buffer + tokens.size(), buffer + currentOffset, existing * sizeof(Token));
    memcpy(buffer, tokens.data(), tokens.size() * sizeof(Token));

    currentOffset = 0;
    count = (uint32_t)tokens.size() + existing;
}

} // namespace slang<commit_msg>Fix Clang warning<commit_after>//------------------------------------------------------------------------------
// ParserBase.cpp
// Base class for parsing.
//
// File is under the MIT license; see LICENSE for details.
//------------------------------------------------------------------------------
#include "slang/parsing/ParserBase.h"

#include "slang/parsing/Preprocessor.h"
#include "slang/util/BumpAllocator.h"

namespace slang {

ParserBase::ParserBase(Preprocessor& preprocessor) :
    alloc(preprocessor.getAllocator()), window(preprocessor) {
}

void ParserBase::prependSkippedTokens(Token& token) {
    SmallVectorSized<Trivia, 8> buffer;
    buffer.append(Trivia{ TriviaKind::SkippedTokens, skippedTokens.copy(alloc) });
    buffer.appendRange(token.trivia());

    token = token.withTrivia(alloc, buffer.copy(alloc));
    skippedTokens.clear();
}

Diagnostics& ParserBase::getDiagnostics() {
    return window.tokenSource.getDiagnostics();
}

Diagnostic& ParserBase::addDiag(DiagCode code, SourceLocation location) {
    // If we issued this error in response to seeing an EOF token, back up and put
    // the error on the last consumed token instead.
    if (peek(TokenKind::EndOfFile) && peek().location() == location) {
        Token last = getLastConsumed();
        if (last)
            location = last.location() + last.rawText().size();
    }

    return getDiagnostics().add(code, location);
}

Token ParserBase::peek(uint32_t offset) {
    while (window.currentOffset + offset >= window.count)
        window.addNew();
    return window.buffer[window.currentOffset + offset];
}

Token ParserBase::peek() {
    if (!window.currentToken) {
        if (window.currentOffset >= window.count)
            window.addNew();
        window.currentToken = window.buffer[window.currentOffset];
    }
    ASSERT(window.currentToken);
    return window.currentToken;
}

bool ParserBase::peek(TokenKind kind) {
    return peek().kind == kind;
}

Token ParserBase::consume() {
    auto result = peek();
    window.moveToNext();
    if (!skippedTokens.empty())
        prependSkippedTokens(result);
    return result;
}

Token ParserBase::consumeIf(TokenKind kind) {
    if (peek(kind))
        return consume();
    return Token();
}

Token ParserBase::expect(TokenKind kind) {
    // keep this method small so that it gets inlined
    auto result = peek();
    if (result.kind != kind)
        result = Token::createExpected(alloc, getDiagnostics(), result, kind, window.lastConsumed);
    else
        window.moveToNext();

    if (!skippedTokens.empty())
        prependSkippedTokens(result);

    return result;
}

void ParserBase::skipToken(std::optional<DiagCode> diagCode) {
    auto token = peek();
    skippedTokens.append(token);
    window.moveToNext();

    if (diagCode)
        addDiag(*diagCode, token.location()) << token.range();
}

void ParserBase::pushTokens(span<const Token> tokens) {
    window.insertHead(tokens);
}

Token ParserBase::missingToken(TokenKind kind, SourceLocation location) {
    return Token::createMissing(alloc, kind, location);
}

Token ParserBase::getLastConsumed() const {
    return window.lastConsumed;
}

void ParserBase::Window::addNew() {
    if (count >= capacity) {
        // shift tokens to the left if we are too far to the right
        uint32_t shift = count - currentOffset;
        if (currentOffset > (capacity >> 1)) {
            if (shift > 0)
                memmove(buffer, buffer + currentOffset, shift * sizeof(Token));
        }
        else {
            capacity *= 2;
            Token* newBuffer = new Token[capacity];
            memcpy(newBuffer, buffer + currentOffset, shift * sizeof(Token));

            delete[] buffer;
            buffer = newBuffer;
        }

        count -= currentOffset;
        currentOffset = 0;
    }

    buffer[count] = tokenSource.next();
    count++;
}

void ParserBase::Window::moveToNext() {
    lastConsumed = currentToken;
    currentToken = Token();
    currentOffset++;
}

void ParserBase::Window::insertHead(span<const Token> tokens) {
    if (currentOffset >= (uint32_t)tokens.size()) {
        currentOffset -= (uint32_t)tokens.size();
        memcpy(buffer + currentOffset, tokens.data(), (uint32_t)tokens.size() * sizeof(Token));
        return;
    }

    uint32_t existing = count - currentOffset;
    ASSERT((uint32_t)tokens.size() + existing < capacity);

    memmove(buffer + tokens.size(), buffer + currentOffset, existing * sizeof(Token));
    memcpy(buffer, tokens.data(), (uint32_t)tokens.size() * sizeof(Token));

    currentOffset = 0;
    count = (uint32_t)tokens.size() + existing;
}

} // namespace slang<|endoftext|>


<commit_before>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// 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.

#ifndef RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_
#define RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_

#include <memory>
#include <stdexcept>

#include "rcl/types.h"

#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"

#include "rmw/serialized_message.h"

namespace rclcpp
{
namespace message_memory_strategy
{

/// Default allocation strategy for messages received by subscriptions.
/** A message memory strategy must be templated on the type of the subscription it belongs to. */
template<typename MessageT, typename Alloc = std::allocator<void>>
class MessageMemoryStrategy
{
public:
  RCLCPP_SMART_PTR_DEFINITIONS(MessageMemoryStrategy)

  using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
  using MessageAlloc = typename MessageAllocTraits::allocator_type;
  using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;

  using SerializedMessageAllocTraits = allocator::AllocRebind<rcl_serialized_message_t, Alloc>;
  using SerializedMessageAlloc = typename SerializedMessageAllocTraits::allocator_type;
  using SerializedMessageDeleter =
    allocator::Deleter<SerializedMessageAlloc, rcl_serialized_message_t>;

  using BufferAllocTraits = allocator::AllocRebind<char, Alloc>;
  using BufferAlloc = typename BufferAllocTraits::allocator_type;
  using BufferDeleter = allocator::Deleter<BufferAlloc, char>;

  MessageMemoryStrategy()
  {
    message_allocator_ = std::make_shared<MessageAlloc>();
    serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>();
    buffer_allocator_ = std::make_shared<BufferAlloc>();
    rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
  }

  explicit MessageMemoryStrategy(std::shared_ptr<Alloc> allocator)
  {
    message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
    serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>(*allocator.get());
    buffer_allocator_ = std::make_shared<BufferAlloc>(*allocator.get());
    rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
  }

  /// Default factory method
  static SharedPtr create_default()
  {
    return std::make_shared<MessageMemoryStrategy<MessageT, Alloc>>(std::make_shared<Alloc>());
  }

  /// By default, dynamically allocate a new message.
  /** \return Shared pointer to the new message. */
  virtual std::shared_ptr<MessageT> borrow_message()
  {
    return std::allocate_shared<MessageT, MessageAlloc>(*message_allocator_.get());
  }

  virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message(size_t capacity)
  {
    auto msg = new rcl_serialized_message_t;
    *msg = rmw_get_zero_initialized_serialized_message();
    auto ret = rmw_serialized_message_init(msg, capacity, &rcutils_allocator_);
    if (ret != RCL_RET_OK) {
      rclcpp::exceptions::throw_from_rcl_error(ret);
    }

    auto serialized_msg = std::shared_ptr<rcl_serialized_message_t>(msg,
        [](rmw_serialized_message_t * msg) {
          auto ret = rmw_serialized_message_fini(msg);
          delete msg;
          if (ret != RCL_RET_OK) {
            rclcpp::exceptions::throw_from_rcl_error(ret, "leaking memory");
          }
        });

    return serialized_msg;
  }

  virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message()
  {
    return borrow_serialized_message(default_buffer_capacity_);
  }

  virtual void set_default_buffer_capacity(size_t capacity)
  {
    default_buffer_capacity_ = capacity;
  }

  /// Release ownership of the message, which will deallocate it if it has no more owners.
  /** \param[in] msg Shared pointer to the message we are returning. */
  virtual void return_message(std::shared_ptr<MessageT> & msg)
  {
    msg.reset();
  }

  virtual void return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & serialized_msg)
  {
    serialized_msg.reset();
  }

  std::shared_ptr<MessageAlloc> message_allocator_;
  MessageDeleter message_deleter_;

  std::shared_ptr<SerializedMessageAlloc> serialized_message_allocator_;
  SerializedMessageDeleter serialized_message_deleter_;

  std::shared_ptr<BufferAlloc> buffer_allocator_;
  BufferDeleter buffer_deleter_;
  size_t default_buffer_capacity_ = 0;

  rcutils_allocator_t rcutils_allocator_;
};

}  // namespace message_memory_strategy
}  // namespace rclcpp

#endif  // RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_
<commit_msg>log error message instead of throwing exception in destructor (#535)<commit_after>// Copyright 2015 Open Source Robotics Foundation, Inc.
//
// 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.

#ifndef RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_
#define RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_

#include <memory>
#include <stdexcept>

#include "rcl/types.h"

#include "rclcpp/allocator/allocator_common.hpp"
#include "rclcpp/exceptions.hpp"
#include "rclcpp/macros.hpp"
#include "rclcpp/visibility_control.hpp"

#include "rcutils/logging_macros.h"

#include "rmw/serialized_message.h"

namespace rclcpp
{
namespace message_memory_strategy
{

/// Default allocation strategy for messages received by subscriptions.
/** A message memory strategy must be templated on the type of the subscription it belongs to. */
template<typename MessageT, typename Alloc = std::allocator<void>>
class MessageMemoryStrategy
{
public:
  RCLCPP_SMART_PTR_DEFINITIONS(MessageMemoryStrategy)

  using MessageAllocTraits = allocator::AllocRebind<MessageT, Alloc>;
  using MessageAlloc = typename MessageAllocTraits::allocator_type;
  using MessageDeleter = allocator::Deleter<MessageAlloc, MessageT>;

  using SerializedMessageAllocTraits = allocator::AllocRebind<rcl_serialized_message_t, Alloc>;
  using SerializedMessageAlloc = typename SerializedMessageAllocTraits::allocator_type;
  using SerializedMessageDeleter =
    allocator::Deleter<SerializedMessageAlloc, rcl_serialized_message_t>;

  using BufferAllocTraits = allocator::AllocRebind<char, Alloc>;
  using BufferAlloc = typename BufferAllocTraits::allocator_type;
  using BufferDeleter = allocator::Deleter<BufferAlloc, char>;

  MessageMemoryStrategy()
  {
    message_allocator_ = std::make_shared<MessageAlloc>();
    serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>();
    buffer_allocator_ = std::make_shared<BufferAlloc>();
    rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
  }

  explicit MessageMemoryStrategy(std::shared_ptr<Alloc> allocator)
  {
    message_allocator_ = std::make_shared<MessageAlloc>(*allocator.get());
    serialized_message_allocator_ = std::make_shared<SerializedMessageAlloc>(*allocator.get());
    buffer_allocator_ = std::make_shared<BufferAlloc>(*allocator.get());
    rcutils_allocator_ = allocator::get_rcl_allocator<char, BufferAlloc>(*buffer_allocator_.get());
  }

  /// Default factory method
  static SharedPtr create_default()
  {
    return std::make_shared<MessageMemoryStrategy<MessageT, Alloc>>(std::make_shared<Alloc>());
  }

  /// By default, dynamically allocate a new message.
  /** \return Shared pointer to the new message. */
  virtual std::shared_ptr<MessageT> borrow_message()
  {
    return std::allocate_shared<MessageT, MessageAlloc>(*message_allocator_.get());
  }

  virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message(size_t capacity)
  {
    auto msg = new rcl_serialized_message_t;
    *msg = rmw_get_zero_initialized_serialized_message();
    auto ret = rmw_serialized_message_init(msg, capacity, &rcutils_allocator_);
    if (ret != RCL_RET_OK) {
      rclcpp::exceptions::throw_from_rcl_error(ret);
    }

    auto serialized_msg = std::shared_ptr<rcl_serialized_message_t>(msg,
        [](rmw_serialized_message_t * msg) {
          auto ret = rmw_serialized_message_fini(msg);
          delete msg;
          if (ret != RCL_RET_OK) {
            RCUTILS_LOG_ERROR_NAMED(
              "rclcpp",
              "failed to destroy serialized message: %s", rcl_get_error_string_safe());
          }
        });

    return serialized_msg;
  }

  virtual std::shared_ptr<rcl_serialized_message_t> borrow_serialized_message()
  {
    return borrow_serialized_message(default_buffer_capacity_);
  }

  virtual void set_default_buffer_capacity(size_t capacity)
  {
    default_buffer_capacity_ = capacity;
  }

  /// Release ownership of the message, which will deallocate it if it has no more owners.
  /** \param[in] msg Shared pointer to the message we are returning. */
  virtual void return_message(std::shared_ptr<MessageT> & msg)
  {
    msg.reset();
  }

  virtual void return_serialized_message(std::shared_ptr<rcl_serialized_message_t> & serialized_msg)
  {
    serialized_msg.reset();
  }

  std::shared_ptr<MessageAlloc> message_allocator_;
  MessageDeleter message_deleter_;

  std::shared_ptr<SerializedMessageAlloc> serialized_message_allocator_;
  SerializedMessageDeleter serialized_message_deleter_;

  std::shared_ptr<BufferAlloc> buffer_allocator_;
  BufferDeleter buffer_deleter_;
  size_t default_buffer_capacity_ = 0;

  rcutils_allocator_t rcutils_allocator_;
};

}  // namespace message_memory_strategy
}  // namespace rclcpp

#endif  // RCLCPP__MESSAGE_MEMORY_STRATEGY_HPP_
<|endoftext|>