<commit_before>#ifndef option_manager_hh_INCLUDED
#define option_manager_hh_INCLUDED

#include "completion.hh"
#include "containers.hh"
#include "exception.hh"
#include "flags.hh"
#include "option_types.hh"
#include "vector.hh"

#include <memory>
#include <type_traits>

namespace Kakoune
{

class OptionManager;

enum class OptionFlags
{
    None   = 0,
    Hidden = 1,
};

template<> struct WithBitOps<OptionFlags> : std::true_type {};

class OptionDesc
{
public:
    OptionDesc(String name, String docstring, OptionFlags flags);

    const String& name() const { return m_name; }
    const String& docstring() const { return m_docstring; }

    OptionFlags flags() const { return m_flags; }

private:
    String m_name;
    String m_docstring;
    OptionFlags  m_flags;
};

class Option
{
public:
    virtual ~Option() = default;

    template<typename T> const T& get() const;
    template<typename T> T& get_mutable();
    template<typename T> void set(const T& val, bool notify=true);
    template<typename T> bool is_of_type() const;

    virtual String get_as_string() const = 0;
    virtual void   set_from_string(StringView str) = 0;
    virtual void   add_from_string(StringView str) = 0;

    virtual Option* clone(OptionManager& manager) const = 0;
    OptionManager& manager() const { return m_manager; }

    const String& name() const { return m_desc.name(); }
    const String& docstring() const { return m_desc.docstring(); }
    OptionFlags flags() const { return m_desc.flags(); }

protected:
    Option(const OptionDesc& desc, OptionManager& manager);

    OptionManager& m_manager;
    const OptionDesc& m_desc;
};

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

    virtual void on_option_changed(const Option& option) = 0;
};

class OptionManager : private OptionManagerWatcher
{
public:
    OptionManager(OptionManager& parent);
    ~OptionManager();

    Option& operator[] (StringView name);
    const Option& operator[] (StringView name) const;
    Option& get_local_option(StringView name);

    void unset_option(StringView name);

    using OptionList = Vector<const Option*>;
    OptionList flatten_options() const;

    void register_watcher(OptionManagerWatcher& watcher);
    void unregister_watcher(OptionManagerWatcher& watcher);

    void on_option_changed(const Option& option) override;
private:
    OptionManager()
        : m_parent(nullptr) {}
    // the only one allowed to construct a root option manager
    friend class Scope;
    friend class OptionsRegistry;

    Vector<std::unique_ptr<Option>, MemoryDomain::Options> m_options;
    OptionManager* m_parent;

    Vector<OptionManagerWatcher*, MemoryDomain::Options> m_watchers;
};

template<typename T>
class TypedOption : public Option
{
public:
    TypedOption(OptionManager& manager, const OptionDesc& desc, const T& value)
        : Option(desc, manager), m_value(value) {}

    void set(T value, bool notify = true)
    {
        validate(value);
        if (m_value != value)
        {
            m_value = std::move(value);
            if (notify)
                manager().on_option_changed(*this);
        }
    }
    const T& get() const { return m_value; }
    T& get_mutable() { return m_value; }

    String get_as_string() const override
    {
        return option_to_string(m_value);
    }
    void set_from_string(StringView str) override
    {
        T val;
        option_from_string(str, val);
        set(std::move(val));
    }
    void add_from_string(StringView str) override
    {
        if (option_add(m_value, str))
            m_manager.on_option_changed(*this);
    }

    using Alloc = Allocator<TypedOption, MemoryDomain::Options>;
    static void* operator new (std::size_t sz)
    {
        kak_assert(sz == sizeof(TypedOption));
        return Alloc{}.allocate(1);
    }

    static void operator delete (void* ptr)
    {
        return Alloc{}.deallocate(reinterpret_cast<TypedOption*>(ptr), 1);
    }
private:
    virtual void validate(const T& value) const {}
    T m_value;
};

template<typename T, void (*validator)(const T&)>
class TypedCheckedOption : public TypedOption<T>
{
    using TypedOption<T>::TypedOption;

    Option* clone(OptionManager& manager) const override
    {
        return new TypedCheckedOption{manager, this->m_desc, this->get()};
    }

    void validate(const T& value) const override { if (validator != nullptr) validator(value); }
};

template<typename T> const T& Option::get() const
{
    auto* typed_opt = dynamic_cast<const TypedOption<T>*>(this);
    if (not typed_opt)
        throw runtime_error(format("option '{}' is not of type '{}'", name(), typeid(T).name()));
    return typed_opt->get();
}

template<typename T> T& Option::get_mutable()
{
    return const_cast<T&>(get<T>());
}

template<typename T> void Option::set(const T& val, bool notify)
{
    auto* typed_opt = dynamic_cast<TypedOption<T>*>(this);
    if (not typed_opt)
        throw runtime_error(format("option '{}' is not of type '{}'", name(), typeid(T).name()));
    return typed_opt->set(val, notify);
}

template<typename T> bool Option::is_of_type() const
{
    return dynamic_cast<const TypedOption<T>*>(this) != nullptr;
}

template<typename T>
auto find_option(T& container, StringView name) -> decltype(container.begin())
{
    using ptr_type = decltype(*container.begin());
    return find_if(container, [&name](const ptr_type& opt) { return opt->name() == name; });
}

class OptionsRegistry
{
public:
    OptionsRegistry(OptionManager& global_manager) : m_global_manager(global_manager) {}

    template<typename T, void (*validator)(const T&) = nullptr>
    Option& declare_option(StringView name, StringView docstring,
                           const T& value,
                           OptionFlags flags = OptionFlags::None)
    {
        auto& opts = m_global_manager.m_options;
        auto it = find_option(opts, name);
        if (it != opts.end())
        {
            if ((*it)->is_of_type<T>() and (*it)->flags() == flags)
                return **it;
            throw runtime_error(format("option '{}' already declared with different type or flags", name));
        }
        m_descs.emplace_back(new OptionDesc{name.str(), format("({}): {}", option_type_name<T>::name(), docstring), flags});
        opts.emplace_back(new TypedCheckedOption<T, validator>{m_global_manager, *m_descs.back(), value});
        return *opts.back();
    }

    const OptionDesc* option_desc(StringView name) const
    {
        auto it = find_if(m_descs,
                          [&name](const std::unique_ptr<OptionDesc>& opt)
                          { return opt->name() == name; });
        return it != m_descs.end() ? it->get() : nullptr;
    }

    bool option_exists(StringView name) const { return option_desc(name) != nullptr; }

    CandidateList complete_option_name(StringView prefix, ByteCount cursor_pos) const;
private:
    OptionManager& m_global_manager;
    Vector<std::unique_ptr<OptionDesc>, MemoryDomain::Options> m_descs;
};

}

#endif // option_manager_hh_INCLUDED
<commit_msg>Tweak format of option docstrings<commit_after>#ifndef option_manager_hh_INCLUDED
#define option_manager_hh_INCLUDED

#include "completion.hh"
#include "containers.hh"
#include "exception.hh"
#include "flags.hh"
#include "option_types.hh"
#include "vector.hh"

#include <memory>
#include <type_traits>

namespace Kakoune
{

class OptionManager;

enum class OptionFlags
{
    None   = 0,
    Hidden = 1,
};

template<> struct WithBitOps<OptionFlags> : std::true_type {};

class OptionDesc
{
public:
    OptionDesc(String name, String docstring, OptionFlags flags);

    const String& name() const { return m_name; }
    const String& docstring() const { return m_docstring; }

    OptionFlags flags() const { return m_flags; }

private:
    String m_name;
    String m_docstring;
    OptionFlags  m_flags;
};

class Option
{
public:
    virtual ~Option() = default;

    template<typename T> const T& get() const;
    template<typename T> T& get_mutable();
    template<typename T> void set(const T& val, bool notify=true);
    template<typename T> bool is_of_type() const;

    virtual String get_as_string() const = 0;
    virtual void   set_from_string(StringView str) = 0;
    virtual void   add_from_string(StringView str) = 0;

    virtual Option* clone(OptionManager& manager) const = 0;
    OptionManager& manager() const { return m_manager; }

    const String& name() const { return m_desc.name(); }
    const String& docstring() const { return m_desc.docstring(); }
    OptionFlags flags() const { return m_desc.flags(); }

protected:
    Option(const OptionDesc& desc, OptionManager& manager);

    OptionManager& m_manager;
    const OptionDesc& m_desc;
};

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

    virtual void on_option_changed(const Option& option) = 0;
};

class OptionManager : private OptionManagerWatcher
{
public:
    OptionManager(OptionManager& parent);
    ~OptionManager();

    Option& operator[] (StringView name);
    const Option& operator[] (StringView name) const;
    Option& get_local_option(StringView name);

    void unset_option(StringView name);

    using OptionList = Vector<const Option*>;
    OptionList flatten_options() const;

    void register_watcher(OptionManagerWatcher& watcher);
    void unregister_watcher(OptionManagerWatcher& watcher);

    void on_option_changed(const Option& option) override;
private:
    OptionManager()
        : m_parent(nullptr) {}
    // the only one allowed to construct a root option manager
    friend class Scope;
    friend class OptionsRegistry;

    Vector<std::unique_ptr<Option>, MemoryDomain::Options> m_options;
    OptionManager* m_parent;

    Vector<OptionManagerWatcher*, MemoryDomain::Options> m_watchers;
};

template<typename T>
class TypedOption : public Option
{
public:
    TypedOption(OptionManager& manager, const OptionDesc& desc, const T& value)
        : Option(desc, manager), m_value(value) {}

    void set(T value, bool notify = true)
    {
        validate(value);
        if (m_value != value)
        {
            m_value = std::move(value);
            if (notify)
                manager().on_option_changed(*this);
        }
    }
    const T& get() const { return m_value; }
    T& get_mutable() { return m_value; }

    String get_as_string() const override
    {
        return option_to_string(m_value);
    }
    void set_from_string(StringView str) override
    {
        T val;
        option_from_string(str, val);
        set(std::move(val));
    }
    void add_from_string(StringView str) override
    {
        if (option_add(m_value, str))
            m_manager.on_option_changed(*this);
    }

    using Alloc = Allocator<TypedOption, MemoryDomain::Options>;
    static void* operator new (std::size_t sz)
    {
        kak_assert(sz == sizeof(TypedOption));
        return Alloc{}.allocate(1);
    }

    static void operator delete (void* ptr)
    {
        return Alloc{}.deallocate(reinterpret_cast<TypedOption*>(ptr), 1);
    }
private:
    virtual void validate(const T& value) const {}
    T m_value;
};

template<typename T, void (*validator)(const T&)>
class TypedCheckedOption : public TypedOption<T>
{
    using TypedOption<T>::TypedOption;

    Option* clone(OptionManager& manager) const override
    {
        return new TypedCheckedOption{manager, this->m_desc, this->get()};
    }

    void validate(const T& value) const override { if (validator != nullptr) validator(value); }
};

template<typename T> const T& Option::get() const
{
    auto* typed_opt = dynamic_cast<const TypedOption<T>*>(this);
    if (not typed_opt)
        throw runtime_error(format("option '{}' is not of type '{}'", name(), typeid(T).name()));
    return typed_opt->get();
}

template<typename T> T& Option::get_mutable()
{
    return const_cast<T&>(get<T>());
}

template<typename T> void Option::set(const T& val, bool notify)
{
    auto* typed_opt = dynamic_cast<TypedOption<T>*>(this);
    if (not typed_opt)
        throw runtime_error(format("option '{}' is not of type '{}'", name(), typeid(T).name()));
    return typed_opt->set(val, notify);
}

template<typename T> bool Option::is_of_type() const
{
    return dynamic_cast<const TypedOption<T>*>(this) != nullptr;
}

template<typename T>
auto find_option(T& container, StringView name) -> decltype(container.begin())
{
    using ptr_type = decltype(*container.begin());
    return find_if(container, [&name](const ptr_type& opt) { return opt->name() == name; });
}

class OptionsRegistry
{
public:
    OptionsRegistry(OptionManager& global_manager) : m_global_manager(global_manager) {}

    template<typename T, void (*validator)(const T&) = nullptr>
    Option& declare_option(StringView name, StringView docstring,
                           const T& value,
                           OptionFlags flags = OptionFlags::None)
    {
        auto& opts = m_global_manager.m_options;
        auto it = find_option(opts, name);
        if (it != opts.end())
        {
            if ((*it)->is_of_type<T>() and (*it)->flags() == flags)
                return **it;
            throw runtime_error(format("option '{}' already declared with different type or flags", name));
        }
        String doc =  docstring.empty() ? format("[{}]", option_type_name<T>::name())
                                        : format("[{}] - {}", option_type_name<T>::name(), docstring);
        m_descs.emplace_back(new OptionDesc{name.str(), std::move(doc), flags});
        opts.emplace_back(new TypedCheckedOption<T, validator>{m_global_manager, *m_descs.back(), value});
        return *opts.back();
    }

    const OptionDesc* option_desc(StringView name) const
    {
        auto it = find_if(m_descs,
                          [&name](const std::unique_ptr<OptionDesc>& opt)
                          { return opt->name() == name; });
        return it != m_descs.end() ? it->get() : nullptr;
    }

    bool option_exists(StringView name) const { return option_desc(name) != nullptr; }

    CandidateList complete_option_name(StringView prefix, ByteCount cursor_pos) const;
private:
    OptionManager& m_global_manager;
    Vector<std::unique_ptr<OptionDesc>, MemoryDomain::Options> m_descs;
};

}

#endif // option_manager_hh_INCLUDED
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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 <osg/GLExtensions>
#include <osg/Texture2D>
#include <osg/State>
#include <osg/GLU>

typedef void (APIENTRY * MyCompressedTexImage2DArbProc) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);

using namespace osg;

Texture2D::Texture2D():
            _textureWidth(0),
            _textureHeight(0),
            _numMipmapLevels(0)
{
    setUseHardwareMipMapGeneration(true);
}

Texture2D::Texture2D(osg::Image* image):
            _textureWidth(0),
            _textureHeight(0),
            _numMipmapLevels(0)
{
    setUseHardwareMipMapGeneration(true);
    setImage(image);
}

Texture2D::Texture2D(const Texture2D& text,const CopyOp& copyop):
            Texture(text,copyop),
            _image(copyop(text._image.get())),
            _textureWidth(text._textureWidth),
            _textureHeight(text._textureHeight),
            _numMipmapLevels(text._numMipmapLevels),
            _subloadCallback(text._subloadCallback)
{
}

Texture2D::~Texture2D()
{
}

int Texture2D::compare(const StateAttribute& sa) const
{
    // check the types are equal and then create the rhs variable
    // used by the COMPARE_StateAttribute_Paramter macro's below.
    COMPARE_StateAttribute_Types(Texture2D,sa)

    if (_image!=rhs._image) // smart pointer comparison.
    {
        if (_image.valid())
        {
            if (rhs._image.valid())
            {
                int result = _image->compare(*rhs._image);
                if (result!=0) return result;
            }
            else
            {
                return 1; // valid lhs._image is greater than null.
            }
        }
        else if (rhs._image.valid())
        {
            return -1; // valid rhs._image is greater than null.
        }
    }

    int result = compareTexture(rhs);
    if (result!=0) return result;

    // compare each paramter in turn against the rhs.
    COMPARE_StateAttribute_Parameter(_textureWidth)
    COMPARE_StateAttribute_Parameter(_textureHeight)
    COMPARE_StateAttribute_Parameter(_subloadCallback)

    return 0; // passed all the above comparison macro's, must be equal.
}

void Texture2D::setImage(Image* image)
{
    _image = image;
    _modifiedTag.setAllElementsTo(0);
}

void Texture2D::apply(State& state) const
{

    //state.setReportGLErrors(true);

    // get the contextID (user defined ID of 0 upwards) for the
    // current OpenGL context.
    const unsigned int contextID = state.getContextID();

    // get the texture object for the current contextID.
    TextureObject* textureObject = getTextureObject(contextID);

    if (textureObject != 0)
    {
        textureObject->bind();

        if (getTextureParameterDirty(state.getContextID()))
            applyTexParameters(GL_TEXTURE_2D,state);

        if (_subloadCallback.valid())
        {
            _subloadCallback->subload(*this,state);
        }
        else if (_image.valid() && getModifiedTag(contextID) != _image->getModifiedTag())
        {
            applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(),
                                    _textureWidth, _textureHeight, _numMipmapLevels);

            // update the modified tag to show that it is upto date.
            getModifiedTag(contextID) = _image->getModifiedTag();

        }

    }
    else if (_subloadCallback.valid())
    {

        _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_2D);

        textureObject->bind();

        applyTexParameters(GL_TEXTURE_2D,state);

        _subloadCallback->load(*this,state);

        textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);

        // in theory the following line is redundent, but in practice
        // have found that the first frame drawn doesn't apply the textures
        // unless a second bind is called?!!
        // perhaps it is the first glBind which is not required...
        //glBindTexture( GL_TEXTURE_2D, handle );

    }
    else if (_image.valid() && _image->data())
    {

        // compute the internal texture format, this set the _internalFormat to an appropriate value.
        computeInternalFormat();

        // compute the dimensions of the texture.
        computeRequiredTextureDimensions(state,*_image,_textureWidth, _textureHeight, _numMipmapLevels);

        _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->reuseOrGenerateTextureObject(
                contextID,GL_TEXTURE_2D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);

        textureObject->bind();

        applyTexParameters(GL_TEXTURE_2D,state);

        if (textureObject->isAllocated())
        {
            //std::cout<<"Reusing texture object"<<std::endl;
            applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(),
                                 _textureWidth, _textureHeight, _numMipmapLevels);
        }
        else
        {
            //std::cout<<"Creating new texture object"<<std::endl;
            applyTexImage2D_load(state,GL_TEXTURE_2D,_image.get(),
                                 _textureWidth, _textureHeight, _numMipmapLevels);

            textureObject->setAllocated(true);
        }

        // update the modified tag to show that it is upto date.
        getModifiedTag(contextID) = _image->getModifiedTag();

        if (_unrefImageDataAfterApply && areAllTextureObjectsLoaded())
        {
            Texture2D* non_const_this = const_cast<Texture2D*>(this);
            non_const_this->_image = 0;
        }

        // in theory the following line is redundent, but in practice
        // have found that the first frame drawn doesn't apply the textures
        // unless a second bind is called?!!
        // perhaps it is the first glBind which is not required...
        //glBindTexture( GL_TEXTURE_2D, handle );

    }
    else
    {
        glBindTexture( GL_TEXTURE_2D, 0 );
    }
}

void Texture2D::computeInternalFormat() const
{
    if (_image.valid()) computeInternalFormatWithImage(*_image);
}

void Texture2D::copyTexImage2D(State& state, int x, int y, int width, int height )
{
    const unsigned int contextID = state.getContextID();

    // get the globj for the current contextID.
    TextureObject* textureObject = getTextureObject(contextID);

    if (textureObject)
    {
        if (width==(int)_textureWidth && height==(int)_textureHeight)
        {
            // we have a valid texture object which is the right size
            // so lets play clever and use copyTexSubImage2D instead.
            // this allows use to reuse the texture object and avoid
            // expensive memory allocations.
            copyTexSubImage2D(state,0 ,0, x, y, width, height);
            return;
        }
        // the relevent texture object is not of the right size so
        // needs to been deleted
        // remove previously bound textures.
        dirtyTextureObject();
        // note, dirtyTextureObject() dirties all the texture objects for
        // this texture, is this right?  Perhaps we should dirty just the
        // one for this context.  Note sure yet will leave till later.
        // RO July 2001.
    }

    // remove any previously assigned images as these are nolonger valid.
    _image = NULL;

    // switch off mip-mapping.
    _min_filter = LINEAR;
    _mag_filter = LINEAR;

    _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_2D);

    textureObject->bind();

    applyTexParameters(GL_TEXTURE_2D,state);
    glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, x, y, width, height, 0 );

    _textureWidth = width;
    _textureHeight = height;
    _numMipmapLevels = 1;

    textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);

    // inform state that this texture is the current one bound.
    state.haveAppliedAttribute(this);
}

void Texture2D::copyTexSubImage2D(State& state, int xoffset, int yoffset, int x, int y, int width, int height )
{
    const unsigned int contextID = state.getContextID();

    // get the texture object for the current contextID.
    TextureObject* textureObject = getTextureObject(contextID);

    if (textureObject)
    {
        // we have a valid image
        textureObject->bind();

        applyTexParameters(GL_TEXTURE_2D,state);
        glCopyTexSubImage2D( GL_TEXTURE_2D, 0, xoffset,yoffset, x, y, width, height);

        /* Redundant, delete later */
        //glBindTexture( GL_TEXTURE_2D, handle );

        // inform state that this texture is the current one bound.
        state.haveAppliedAttribute(this);

    }
    else
    {
        // no texture object already exsits for this context so need to
        // create it upfront - simply call copyTexImage2D.
        copyTexImage2D(state,x,y,width,height);
    }
}
<commit_msg>From Romano J M Silva, changed osg::Texture2D::copyTexImage2D so that it uses the _internalFormat for the texture format to read rather than default to GL_RGBA.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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 <osg/GLExtensions>
#include <osg/Texture2D>
#include <osg/State>
#include <osg/GLU>

typedef void (APIENTRY * MyCompressedTexImage2DArbProc) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);

using namespace osg;

Texture2D::Texture2D():
            _textureWidth(0),
            _textureHeight(0),
            _numMipmapLevels(0)
{
    setUseHardwareMipMapGeneration(true);
}

Texture2D::Texture2D(osg::Image* image):
            _textureWidth(0),
            _textureHeight(0),
            _numMipmapLevels(0)
{
    setUseHardwareMipMapGeneration(true);
    setImage(image);
}

Texture2D::Texture2D(const Texture2D& text,const CopyOp& copyop):
            Texture(text,copyop),
            _image(copyop(text._image.get())),
            _textureWidth(text._textureWidth),
            _textureHeight(text._textureHeight),
            _numMipmapLevels(text._numMipmapLevels),
            _subloadCallback(text._subloadCallback)
{
}

Texture2D::~Texture2D()
{
}

int Texture2D::compare(const StateAttribute& sa) const
{
    // check the types are equal and then create the rhs variable
    // used by the COMPARE_StateAttribute_Paramter macro's below.
    COMPARE_StateAttribute_Types(Texture2D,sa)

    if (_image!=rhs._image) // smart pointer comparison.
    {
        if (_image.valid())
        {
            if (rhs._image.valid())
            {
                int result = _image->compare(*rhs._image);
                if (result!=0) return result;
            }
            else
            {
                return 1; // valid lhs._image is greater than null.
            }
        }
        else if (rhs._image.valid())
        {
            return -1; // valid rhs._image is greater than null.
        }
    }

    int result = compareTexture(rhs);
    if (result!=0) return result;

    // compare each paramter in turn against the rhs.
    COMPARE_StateAttribute_Parameter(_textureWidth)
    COMPARE_StateAttribute_Parameter(_textureHeight)
    COMPARE_StateAttribute_Parameter(_subloadCallback)

    return 0; // passed all the above comparison macro's, must be equal.
}

void Texture2D::setImage(Image* image)
{
    _image = image;
    _modifiedTag.setAllElementsTo(0);
}

void Texture2D::apply(State& state) const
{

    //state.setReportGLErrors(true);

    // get the contextID (user defined ID of 0 upwards) for the
    // current OpenGL context.
    const unsigned int contextID = state.getContextID();

    // get the texture object for the current contextID.
    TextureObject* textureObject = getTextureObject(contextID);

    if (textureObject != 0)
    {
        textureObject->bind();

        if (getTextureParameterDirty(state.getContextID()))
            applyTexParameters(GL_TEXTURE_2D,state);

        if (_subloadCallback.valid())
        {
            _subloadCallback->subload(*this,state);
        }
        else if (_image.valid() && getModifiedTag(contextID) != _image->getModifiedTag())
        {
            applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(),
                                    _textureWidth, _textureHeight, _numMipmapLevels);

            // update the modified tag to show that it is upto date.
            getModifiedTag(contextID) = _image->getModifiedTag();

        }

    }
    else if (_subloadCallback.valid())
    {

        _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_2D);

        textureObject->bind();

        applyTexParameters(GL_TEXTURE_2D,state);

        _subloadCallback->load(*this,state);

        textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);

        // in theory the following line is redundent, but in practice
        // have found that the first frame drawn doesn't apply the textures
        // unless a second bind is called?!!
        // perhaps it is the first glBind which is not required...
        //glBindTexture( GL_TEXTURE_2D, handle );

    }
    else if (_image.valid() && _image->data())
    {

        // compute the internal texture format, this set the _internalFormat to an appropriate value.
        computeInternalFormat();

        // compute the dimensions of the texture.
        computeRequiredTextureDimensions(state,*_image,_textureWidth, _textureHeight, _numMipmapLevels);

        _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->reuseOrGenerateTextureObject(
                contextID,GL_TEXTURE_2D,_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);

        textureObject->bind();

        applyTexParameters(GL_TEXTURE_2D,state);

        if (textureObject->isAllocated())
        {
            //std::cout<<"Reusing texture object"<<std::endl;
            applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(),
                                 _textureWidth, _textureHeight, _numMipmapLevels);
        }
        else
        {
            //std::cout<<"Creating new texture object"<<std::endl;
            applyTexImage2D_load(state,GL_TEXTURE_2D,_image.get(),
                                 _textureWidth, _textureHeight, _numMipmapLevels);

            textureObject->setAllocated(true);
        }

        // update the modified tag to show that it is upto date.
        getModifiedTag(contextID) = _image->getModifiedTag();

        if (_unrefImageDataAfterApply && areAllTextureObjectsLoaded())
        {
            Texture2D* non_const_this = const_cast<Texture2D*>(this);
            non_const_this->_image = 0;
        }

        // in theory the following line is redundent, but in practice
        // have found that the first frame drawn doesn't apply the textures
        // unless a second bind is called?!!
        // perhaps it is the first glBind which is not required...
        //glBindTexture( GL_TEXTURE_2D, handle );

    }
    else
    {
        glBindTexture( GL_TEXTURE_2D, 0 );
    }
}

void Texture2D::computeInternalFormat() const
{
    if (_image.valid()) computeInternalFormatWithImage(*_image);
}

void Texture2D::copyTexImage2D(State& state, int x, int y, int width, int height )
{
    const unsigned int contextID = state.getContextID();

    if (_internalFormat==0) _internalFormat=GL_RGBA;

    // get the globj for the current contextID.
    TextureObject* textureObject = getTextureObject(contextID);

    if (textureObject)
    {
        if (width==(int)_textureWidth && height==(int)_textureHeight)
        {
            // we have a valid texture object which is the right size
            // so lets play clever and use copyTexSubImage2D instead.
            // this allows use to reuse the texture object and avoid
            // expensive memory allocations.
            copyTexSubImage2D(state,0 ,0, x, y, width, height);
            return;
        }
        // the relevent texture object is not of the right size so
        // needs to been deleted
        // remove previously bound textures.
        dirtyTextureObject();
        // note, dirtyTextureObject() dirties all the texture objects for
        // this texture, is this right?  Perhaps we should dirty just the
        // one for this context.  Note sure yet will leave till later.
        // RO July 2001.
    }

    // remove any previously assigned images as these are nolonger valid.
    _image = NULL;

    // switch off mip-mapping.
    _min_filter = LINEAR;
    _mag_filter = LINEAR;

    _textureObjectBuffer[contextID] = textureObject = getTextureObjectManager()->generateTextureObject(contextID,GL_TEXTURE_2D);

    textureObject->bind();

    applyTexParameters(GL_TEXTURE_2D,state);
    glCopyTexImage2D( GL_TEXTURE_2D, 0, _internalFormat, x, y, width, height, 0 );

    _textureWidth = width;
    _textureHeight = height;
    _numMipmapLevels = 1;

    textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,1,0);

    // inform state that this texture is the current one bound.
    state.haveAppliedAttribute(this);
}

void Texture2D::copyTexSubImage2D(State& state, int xoffset, int yoffset, int x, int y, int width, int height )
{
    const unsigned int contextID = state.getContextID();

    if (_internalFormat==0) _internalFormat=GL_RGBA;

    // get the texture object for the current contextID.
    TextureObject* textureObject = getTextureObject(contextID);

    if (textureObject)
    {
        // we have a valid image
        textureObject->bind();

        applyTexParameters(GL_TEXTURE_2D,state);
        glCopyTexSubImage2D( GL_TEXTURE_2D, 0, xoffset,yoffset, x, y, width, height);

        /* Redundant, delete later */
        //glBindTexture( GL_TEXTURE_2D, handle );

        // inform state that this texture is the current one bound.
        state.haveAppliedAttribute(this);

    }
    else
    {
        // no texture object already exsits for this context so need to
        // create it upfront - simply call copyTexImage2D.
        copyTexImage2D(state,x,y,width,height);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "walletview.h"

#include "addressbookpage.h"
#include "askpassphrasedialog.h"
#include "bitcoingui.h"
#include "clientmodel.h"
#include "guiutil.h"
#include "masternodeconfig.h"
#include "systemnodeconfig.h"
#include "optionsmodel.h"
#include "overviewpage.h"
#include "receivecoinsdialog.h"
#include "sendcoinsdialog.h"
#include "signverifymessagedialog.h"
#include "transactiontablemodel.h"
#include "transactionview.h"
#include "transactionrecord.h"

#include "walletmodel.h"

#include "ui_interface.h"

#include <QAction>
#include <QActionGroup>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressDialog>
#include <QPushButton>
#include <QVBoxLayout>

WalletView::WalletView(QWidget *parent):
    QStackedWidget(parent),
    clientModel(0),
    walletModel(0)
{
    // Create tabs
    overviewPage = new OverviewPage();

    transactionsPage = new QWidget(this);
    QVBoxLayout *vbox = new QVBoxLayout();
    QHBoxLayout *hbox_buttons = new QHBoxLayout();
    transactionView = new TransactionView(this);
    vbox->addWidget(transactionView);
    QPushButton *exportButton = new QPushButton(tr("&Export"), this);
    exportButton->setToolTip(tr("Export the data in the current tab to a file"));
#ifndef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    exportButton->setIcon(QIcon(":/icons/export"));
#endif
    hbox_buttons->addStretch();

    // Sum of selected transactions
    QLabel *transactionSumLabel = new QLabel(); // Label
    transactionSumLabel->setObjectName("transactionSumLabel"); // Label ID as CSS-reference
    transactionSumLabel->setText(tr("Selected amount:"));
    hbox_buttons->addWidget(transactionSumLabel);

    transactionSum = new QLabel(); // Amount
    transactionSum->setObjectName("transactionSum"); // Label ID as CSS-reference
    transactionSum->setMinimumSize(200, 8);
    transactionSum->setTextInteractionFlags(Qt::TextSelectableByMouse);
    hbox_buttons->addWidget(transactionSum);

    hbox_buttons->addWidget(exportButton);
    vbox->addLayout(hbox_buttons);
    transactionsPage->setLayout(vbox);

    receiveCoinsPage = new ReceiveCoinsDialog();
    sendCoinsPage = new SendCoinsDialog();
    if (masternodeConfig.getCount() >= 0) {
        masternodeListPage = new MasternodeList();
    }
    if (systemnodeConfig.getCount() >= 0) {
        systemnodeListPage = new SystemnodeList();
    }

    addWidget(overviewPage);
    addWidget(transactionsPage);
    addWidget(receiveCoinsPage);
    addWidget(sendCoinsPage);
    if (masternodeConfig.getCount() >= 0) {
        addWidget(masternodeListPage);
    }
    if (systemnodeConfig.getCount() >= 0) {
        addWidget(systemnodeListPage);
    }

    // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page
    connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));

    // Double-clicking on a transaction on the transaction history page shows details
    connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));

    // Update wallet with sum of selected transactions
    connect(transactionView, SIGNAL(trxAmount(QString)), this, SLOT(trxAmount(QString)));

    // Clicking on "Export" allows to export the transaction list
    connect(exportButton, SIGNAL(clicked()), transactionView, SLOT(exportClicked()));

    // Pass through messages from sendCoinsPage
    connect(sendCoinsPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
    // Pass through messages from transactionView
    connect(transactionView, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
}

WalletView::~WalletView()
{
}

void WalletView::setBitcoinGUI(BitcoinGUI *gui)
{
    if (gui)
    {
        // Clicking on a transaction on the overview page simply sends you to transaction history page
        connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), gui, SLOT(gotoHistoryPage()));

        // Receive and report messages
        connect(this, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));

        // Pass through encryption status changed signals
        connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));

        // Pass through transaction notifications
        connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString)));
    }
}

void WalletView::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;

    overviewPage->setClientModel(clientModel);
    sendCoinsPage->setClientModel(clientModel);
    if (masternodeConfig.getCount() >= 0) {
        masternodeListPage->setClientModel(clientModel);
    }
    if (systemnodeConfig.getCount() >= 0) {
        systemnodeListPage->setClientModel(clientModel);
    }
}

void WalletView::setWalletModel(WalletModel *walletModel)
{
    this->walletModel = walletModel;

    // Put transaction list in tabs
    transactionView->setModel(walletModel);
    overviewPage->setWalletModel(walletModel);
    receiveCoinsPage->setModel(walletModel);
    sendCoinsPage->setModel(walletModel);
    if (masternodeConfig.getCount() >= 0) {
        masternodeListPage->setWalletModel(walletModel);
    }
    if (systemnodeConfig.getCount() >= 0) {
        systemnodeListPage->setWalletModel(walletModel);
    }

    if (walletModel)
    {
        // Receive and pass through messages from wallet model
        connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));

        // Handle changes in encryption status
        connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int)));
        updateEncryptionStatus();

        // Balloon pop-up for new transaction
        connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
                this, SLOT(processNewTransaction(QModelIndex,int,int)));

        // Ask for passphrase if needed
        connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));

        // Show progress dialog
        connect(walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
    }
}

void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
    // Prevent balloon-spam when initial block download is in progress
    if (!walletModel || !clientModel || clientModel->inInitialBlockDownload())
        return;

    TransactionTableModel *ttm = walletModel->getTransactionTableModel();
    if (!ttm || ttm->processingQueuedTransactions())
        return;

    QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString();
    qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong();
    QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString();
    QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString();

    // If payment is 500 or 10000 CRW ask to create a Systemnode/Masternode
    qint64 credit = ttm->index(start, TransactionTableModel::AmountCredit, parent).data(Qt::EditRole).toULongLong();
    int typeEnum = ttm->index(start, TransactionTableModel::TypeEnum, parent).data(Qt::EditRole).toInt();

    if (typeEnum == TransactionRecord::SendToSelf)
    {
        AvailableCoinsType coin_type = ONLY_500;
        QString title = tr("Payment to yourself - ") +
            BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), credit);
        QString body = tr("Do you wat to create a new ");
        if (credit == SYSTEMNODE_COLLATERAL * COIN)
        {
            body += "Systemnode?";
        }
        else if (credit == MASTERNODE_COLLATERAL * COIN)
        {
            body += "Masternode?";
            coin_type = ONLY_10000;
        }

        // Display message box
        QMessageBox::StandardButton retval = QMessageBox::question(this, title, body,
                QMessageBox::Yes | QMessageBox::Cancel,
                QMessageBox::Cancel);

        if(retval == QMessageBox::Yes)
        {
            QString hash = ttm->index(start, 0, parent).data(TransactionTableModel::TxHashRole).toString();
            std::vector<COutput> vPossibleCoins;
            pwalletMain->AvailableCoins(vPossibleCoins, true, NULL, coin_type);
            BOOST_FOREACH(COutput& out, vPossibleCoins) {
                if (out.tx->GetHash().ToString() == hash.toStdString())
                {
                    COutPoint outpoint = COutPoint(out.tx->GetHash(), boost::lexical_cast<unsigned int>(out.i));
                    pwalletMain->LockCoin(outpoint);

                    // Generate a key
                    CKey secret;
                    secret.MakeNewKey(false);
                    std::string privateKey = CBitcoinSecret(secret).ToString();

                    systemnodeConfig.add("", "", privateKey, hash.toStdString(), strprintf("%d", out.i));
                    systemnodeListPage->updateMyNodeList(true);
                }
            }
        }
    }
    emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address);
}

void WalletView::gotoOverviewPage()
{
    setCurrentWidget(overviewPage);
}

void WalletView::gotoHistoryPage()
{
    setCurrentWidget(transactionsPage);
}

void WalletView::gotoReceiveCoinsPage()
{
    setCurrentWidget(receiveCoinsPage);
}

void WalletView::gotoSendCoinsPage(QString addr)
{
    setCurrentWidget(sendCoinsPage);

    if (!addr.isEmpty())
        sendCoinsPage->setAddress(addr);
}

void WalletView::gotoMasternodePage()
{
    if (masternodeConfig.getCount() >= 0) {
        setCurrentWidget(masternodeListPage);
    }
}

void WalletView::gotoSystemnodePage()
{
    if (systemnodeConfig.getCount() >= 0) {
        setCurrentWidget(systemnodeListPage);
    }
}

void WalletView::gotoMultisigTab()
{
    // calls show() in showTab_SM()
    MultisigDialog *multisigDialog = new MultisigDialog(this);
    multisigDialog->setAttribute(Qt::WA_DeleteOnClose);
    multisigDialog->setModel(walletModel);
    multisigDialog->showTab(true);
}

void WalletView::gotoSignMessageTab(QString addr)
{
    // calls show() in showTab_SM()
    SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_SM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_SM(addr);
}

void WalletView::gotoVerifyMessageTab(QString addr)
{
    // calls show() in showTab_VM()
    SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_VM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_VM(addr);
}

bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
    return sendCoinsPage->handlePaymentRequest(recipient);
}

void WalletView::showOutOfSyncWarning(bool fShow)
{
    overviewPage->showOutOfSyncWarning(fShow);
}

void WalletView::updateEncryptionStatus()
{
    emit encryptionStatusChanged(walletModel->getEncryptionStatus());
}

void WalletView::encryptWallet(bool status)
{
    if(!walletModel)
        return;
    AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt : AskPassphraseDialog::Decrypt, this);
    dlg.setModel(walletModel);
    dlg.exec();

    updateEncryptionStatus();
}

void WalletView::backupWallet()
{
    QString filename = GUIUtil::getSaveFileName(this,
        tr("Backup Wallet"), QString(),
        tr("Wallet Data (*.dat)"), NULL);

    if (filename.isEmpty())
        return;

    if (!walletModel->backupWallet(filename)) {
        emit message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename),
            CClientUIInterface::MSG_ERROR);
        }
    else {
        emit message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename),
            CClientUIInterface::MSG_INFORMATION);
    }
}

void WalletView::changePassphrase()
{
    AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
    dlg.setModel(walletModel);
    dlg.exec();
}

void WalletView::unlockWallet()
{
    if(!walletModel)
        return;
    // Unlock wallet when requested by wallet model

    if (walletModel->getEncryptionStatus() == WalletModel::Locked)
    {
        AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
        dlg.setModel(walletModel);
        dlg.exec();
    }
}

void WalletView::lockWallet()
{
    if(!walletModel)
        return;

    walletModel->setWalletLocked(true);
}

void WalletView::usedSendingAddresses()
{
    if(!walletModel)
        return;
    AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->setModel(walletModel->getAddressTableModel());
    dlg->show();
}

void WalletView::usedReceivingAddresses()
{
    if(!walletModel)
        return;
    AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->setModel(walletModel->getAddressTableModel());
    dlg->show();
}

void WalletView::showProgress(const QString &title, int nProgress)
{
    if (nProgress == 0)
    {
        progressDialog = new QProgressDialog(title, "", 0, 100);
        progressDialog->setWindowModality(Qt::ApplicationModal);
        progressDialog->setMinimumDuration(0);
        progressDialog->setCancelButton(0);
        progressDialog->setAutoClose(false);
        progressDialog->setValue(0);
    }
    else if (nProgress == 100)
    {
        if (progressDialog)
        {
            progressDialog->close();
            progressDialog->deleteLater();
        }
    }
    else if (progressDialog)
        progressDialog->setValue(nProgress);
}

/** Update wallet with the sum of the selected transactions */
void WalletView::trxAmount(QString amount)
{
    transactionSum->setText(amount);
}
<commit_msg>Fixed condition which asks to create a systemnode<commit_after>// Copyright (c) 2011-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "walletview.h"

#include "addressbookpage.h"
#include "askpassphrasedialog.h"
#include "bitcoingui.h"
#include "clientmodel.h"
#include "guiutil.h"
#include "masternodeconfig.h"
#include "systemnodeconfig.h"
#include "optionsmodel.h"
#include "overviewpage.h"
#include "receivecoinsdialog.h"
#include "sendcoinsdialog.h"
#include "signverifymessagedialog.h"
#include "transactiontablemodel.h"
#include "transactionview.h"
#include "transactionrecord.h"

#include "walletmodel.h"

#include "ui_interface.h"

#include <QAction>
#include <QActionGroup>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QProgressDialog>
#include <QPushButton>
#include <QVBoxLayout>

WalletView::WalletView(QWidget *parent):
    QStackedWidget(parent),
    clientModel(0),
    walletModel(0)
{
    // Create tabs
    overviewPage = new OverviewPage();

    transactionsPage = new QWidget(this);
    QVBoxLayout *vbox = new QVBoxLayout();
    QHBoxLayout *hbox_buttons = new QHBoxLayout();
    transactionView = new TransactionView(this);
    vbox->addWidget(transactionView);
    QPushButton *exportButton = new QPushButton(tr("&Export"), this);
    exportButton->setToolTip(tr("Export the data in the current tab to a file"));
#ifndef Q_OS_MAC // Icons on push buttons are very uncommon on Mac
    exportButton->setIcon(QIcon(":/icons/export"));
#endif
    hbox_buttons->addStretch();

    // Sum of selected transactions
    QLabel *transactionSumLabel = new QLabel(); // Label
    transactionSumLabel->setObjectName("transactionSumLabel"); // Label ID as CSS-reference
    transactionSumLabel->setText(tr("Selected amount:"));
    hbox_buttons->addWidget(transactionSumLabel);

    transactionSum = new QLabel(); // Amount
    transactionSum->setObjectName("transactionSum"); // Label ID as CSS-reference
    transactionSum->setMinimumSize(200, 8);
    transactionSum->setTextInteractionFlags(Qt::TextSelectableByMouse);
    hbox_buttons->addWidget(transactionSum);

    hbox_buttons->addWidget(exportButton);
    vbox->addLayout(hbox_buttons);
    transactionsPage->setLayout(vbox);

    receiveCoinsPage = new ReceiveCoinsDialog();
    sendCoinsPage = new SendCoinsDialog();
    if (masternodeConfig.getCount() >= 0) {
        masternodeListPage = new MasternodeList();
    }
    if (systemnodeConfig.getCount() >= 0) {
        systemnodeListPage = new SystemnodeList();
    }

    addWidget(overviewPage);
    addWidget(transactionsPage);
    addWidget(receiveCoinsPage);
    addWidget(sendCoinsPage);
    if (masternodeConfig.getCount() >= 0) {
        addWidget(masternodeListPage);
    }
    if (systemnodeConfig.getCount() >= 0) {
        addWidget(systemnodeListPage);
    }

    // Clicking on a transaction on the overview pre-selects the transaction on the transaction history page
    connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));

    // Double-clicking on a transaction on the transaction history page shows details
    connect(transactionView, SIGNAL(doubleClicked(QModelIndex)), transactionView, SLOT(showDetails()));

    // Update wallet with sum of selected transactions
    connect(transactionView, SIGNAL(trxAmount(QString)), this, SLOT(trxAmount(QString)));

    // Clicking on "Export" allows to export the transaction list
    connect(exportButton, SIGNAL(clicked()), transactionView, SLOT(exportClicked()));

    // Pass through messages from sendCoinsPage
    connect(sendCoinsPage, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
    // Pass through messages from transactionView
    connect(transactionView, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));
}

WalletView::~WalletView()
{
}

void WalletView::setBitcoinGUI(BitcoinGUI *gui)
{
    if (gui)
    {
        // Clicking on a transaction on the overview page simply sends you to transaction history page
        connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), gui, SLOT(gotoHistoryPage()));

        // Receive and report messages
        connect(this, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));

        // Pass through encryption status changed signals
        connect(this, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));

        // Pass through transaction notifications
        connect(this, SIGNAL(incomingTransaction(QString,int,CAmount,QString,QString)), gui, SLOT(incomingTransaction(QString,int,CAmount,QString,QString)));
    }
}

void WalletView::setClientModel(ClientModel *clientModel)
{
    this->clientModel = clientModel;

    overviewPage->setClientModel(clientModel);
    sendCoinsPage->setClientModel(clientModel);
    if (masternodeConfig.getCount() >= 0) {
        masternodeListPage->setClientModel(clientModel);
    }
    if (systemnodeConfig.getCount() >= 0) {
        systemnodeListPage->setClientModel(clientModel);
    }
}

void WalletView::setWalletModel(WalletModel *walletModel)
{
    this->walletModel = walletModel;

    // Put transaction list in tabs
    transactionView->setModel(walletModel);
    overviewPage->setWalletModel(walletModel);
    receiveCoinsPage->setModel(walletModel);
    sendCoinsPage->setModel(walletModel);
    if (masternodeConfig.getCount() >= 0) {
        masternodeListPage->setWalletModel(walletModel);
    }
    if (systemnodeConfig.getCount() >= 0) {
        systemnodeListPage->setWalletModel(walletModel);
    }

    if (walletModel)
    {
        // Receive and pass through messages from wallet model
        connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), this, SIGNAL(message(QString,QString,unsigned int)));

        // Handle changes in encryption status
        connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SIGNAL(encryptionStatusChanged(int)));
        updateEncryptionStatus();

        // Balloon pop-up for new transaction
        connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
                this, SLOT(processNewTransaction(QModelIndex,int,int)));

        // Ask for passphrase if needed
        connect(walletModel, SIGNAL(requireUnlock()), this, SLOT(unlockWallet()));

        // Show progress dialog
        connect(walletModel, SIGNAL(showProgress(QString,int)), this, SLOT(showProgress(QString,int)));
    }
}

void WalletView::processNewTransaction(const QModelIndex& parent, int start, int /*end*/)
{
    // Prevent balloon-spam when initial block download is in progress
    if (!walletModel || !clientModel || clientModel->inInitialBlockDownload())
        return;

    TransactionTableModel *ttm = walletModel->getTransactionTableModel();
    if (!ttm || ttm->processingQueuedTransactions())
        return;

    QString date = ttm->index(start, TransactionTableModel::Date, parent).data().toString();
    qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent).data(Qt::EditRole).toULongLong();
    QString type = ttm->index(start, TransactionTableModel::Type, parent).data().toString();
    QString address = ttm->index(start, TransactionTableModel::ToAddress, parent).data().toString();

    // If payment is 500 or 10000 CRW ask to create a Systemnode/Masternode
    qint64 credit = ttm->index(start, TransactionTableModel::AmountCredit, parent).data(Qt::EditRole).toULongLong();
    int typeEnum = ttm->index(start, TransactionTableModel::TypeEnum, parent).data(Qt::EditRole).toInt();

    if (typeEnum == TransactionRecord::SendToSelf && (credit == SYSTEMNODE_COLLATERAL * COIN || credit == MASTERNODE_COLLATERAL * COIN))
    {
        AvailableCoinsType coin_type = ONLY_500;
        QString title = tr("Payment to yourself - ") +
            BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), credit);
        QString body = tr("Do you want to create a new ");
        if (credit == SYSTEMNODE_COLLATERAL * COIN)
        {
            body += "Systemnode?";
        }
        else if (credit == MASTERNODE_COLLATERAL * COIN)
        {
            body += "Masternode?";
            coin_type = ONLY_10000;
        }

        // Display message box
        QMessageBox::StandardButton retval = QMessageBox::question(this, title, body,
                QMessageBox::Yes | QMessageBox::Cancel,
                QMessageBox::Cancel);

        if(retval == QMessageBox::Yes)
        {
            QString hash = ttm->index(start, 0, parent).data(TransactionTableModel::TxHashRole).toString();
            std::vector<COutput> vPossibleCoins;
            pwalletMain->AvailableCoins(vPossibleCoins, true, NULL, coin_type);
            BOOST_FOREACH(COutput& out, vPossibleCoins) {
                if (out.tx->GetHash().ToString() == hash.toStdString())
                {
                    COutPoint outpoint = COutPoint(out.tx->GetHash(), boost::lexical_cast<unsigned int>(out.i));
                    pwalletMain->LockCoin(outpoint);

                    // Generate a key
                    CKey secret;
                    secret.MakeNewKey(false);
                    std::string privateKey = CBitcoinSecret(secret).ToString();

                    systemnodeConfig.add("", "", privateKey, hash.toStdString(), strprintf("%d", out.i));
                    systemnodeListPage->updateMyNodeList(true);
                }
            }
        }
    }
    emit incomingTransaction(date, walletModel->getOptionsModel()->getDisplayUnit(), amount, type, address);
}

void WalletView::gotoOverviewPage()
{
    setCurrentWidget(overviewPage);
}

void WalletView::gotoHistoryPage()
{
    setCurrentWidget(transactionsPage);
}

void WalletView::gotoReceiveCoinsPage()
{
    setCurrentWidget(receiveCoinsPage);
}

void WalletView::gotoSendCoinsPage(QString addr)
{
    setCurrentWidget(sendCoinsPage);

    if (!addr.isEmpty())
        sendCoinsPage->setAddress(addr);
}

void WalletView::gotoMasternodePage()
{
    if (masternodeConfig.getCount() >= 0) {
        setCurrentWidget(masternodeListPage);
    }
}

void WalletView::gotoSystemnodePage()
{
    if (systemnodeConfig.getCount() >= 0) {
        setCurrentWidget(systemnodeListPage);
    }
}

void WalletView::gotoMultisigTab()
{
    // calls show() in showTab_SM()
    MultisigDialog *multisigDialog = new MultisigDialog(this);
    multisigDialog->setAttribute(Qt::WA_DeleteOnClose);
    multisigDialog->setModel(walletModel);
    multisigDialog->showTab(true);
}

void WalletView::gotoSignMessageTab(QString addr)
{
    // calls show() in showTab_SM()
    SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_SM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_SM(addr);
}

void WalletView::gotoVerifyMessageTab(QString addr)
{
    // calls show() in showTab_VM()
    SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
    signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
    signVerifyMessageDialog->setModel(walletModel);
    signVerifyMessageDialog->showTab_VM(true);

    if (!addr.isEmpty())
        signVerifyMessageDialog->setAddress_VM(addr);
}

bool WalletView::handlePaymentRequest(const SendCoinsRecipient& recipient)
{
    return sendCoinsPage->handlePaymentRequest(recipient);
}

void WalletView::showOutOfSyncWarning(bool fShow)
{
    overviewPage->showOutOfSyncWarning(fShow);
}

void WalletView::updateEncryptionStatus()
{
    emit encryptionStatusChanged(walletModel->getEncryptionStatus());
}

void WalletView::encryptWallet(bool status)
{
    if(!walletModel)
        return;
    AskPassphraseDialog dlg(status ? AskPassphraseDialog::Encrypt : AskPassphraseDialog::Decrypt, this);
    dlg.setModel(walletModel);
    dlg.exec();

    updateEncryptionStatus();
}

void WalletView::backupWallet()
{
    QString filename = GUIUtil::getSaveFileName(this,
        tr("Backup Wallet"), QString(),
        tr("Wallet Data (*.dat)"), NULL);

    if (filename.isEmpty())
        return;

    if (!walletModel->backupWallet(filename)) {
        emit message(tr("Backup Failed"), tr("There was an error trying to save the wallet data to %1.").arg(filename),
            CClientUIInterface::MSG_ERROR);
        }
    else {
        emit message(tr("Backup Successful"), tr("The wallet data was successfully saved to %1.").arg(filename),
            CClientUIInterface::MSG_INFORMATION);
    }
}

void WalletView::changePassphrase()
{
    AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
    dlg.setModel(walletModel);
    dlg.exec();
}

void WalletView::unlockWallet()
{
    if(!walletModel)
        return;
    // Unlock wallet when requested by wallet model

    if (walletModel->getEncryptionStatus() == WalletModel::Locked)
    {
        AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this);
        dlg.setModel(walletModel);
        dlg.exec();
    }
}

void WalletView::lockWallet()
{
    if(!walletModel)
        return;

    walletModel->setWalletLocked(true);
}

void WalletView::usedSendingAddresses()
{
    if(!walletModel)
        return;
    AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab, this);
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->setModel(walletModel->getAddressTableModel());
    dlg->show();
}

void WalletView::usedReceivingAddresses()
{
    if(!walletModel)
        return;
    AddressBookPage *dlg = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab, this);
    dlg->setAttribute(Qt::WA_DeleteOnClose);
    dlg->setModel(walletModel->getAddressTableModel());
    dlg->show();
}

void WalletView::showProgress(const QString &title, int nProgress)
{
    if (nProgress == 0)
    {
        progressDialog = new QProgressDialog(title, "", 0, 100);
        progressDialog->setWindowModality(Qt::ApplicationModal);
        progressDialog->setMinimumDuration(0);
        progressDialog->setCancelButton(0);
        progressDialog->setAutoClose(false);
        progressDialog->setValue(0);
    }
    else if (nProgress == 100)
    {
        if (progressDialog)
        {
            progressDialog->close();
            progressDialog->deleteLater();
        }
    }
    else if (progressDialog)
        progressDialog->setValue(nProgress);
}

/** Update wallet with the sum of the selected transactions */
void WalletView::trxAmount(QString amount)
{
    transactionSum->setText(amount);
}
<|endoftext|>


<commit_before>#include "read_temp_hum.h"
#include <dht.h>
#include "thermostat.h"
#include "tempe_control.h"

#define TEMPE_HISTORY 6  // How many temperature history value used for filter

using namespace core;

dht DHT;

// Return false if read failed.
bool doReadDHT22() {
  delay(2);  // TODO: it seems DHT not stable without this delay
  int chk = DHT.read22(DHT22_PIN);

  switch (chk) {
    case DHTLIB_OK:
      return true;
    case DHTLIB_ERROR_CHECKSUM:
      Serial.print(F("Checksum error,\n"));
      break;
    case DHTLIB_ERROR_TIMEOUT:
      Serial.print(F("Time out error,\n"));
      break;
    default:
      Serial.print(F("Unknown error,\n"));
      break;
  }

  return false;
}

idType idTempe, idHumi;

void setTempe(int16_t tempe) { store::setAnalog(idTempe, (uint16_t)tempe); }

void updateHumidity(uint16_t hum) { store::setAnalog(idHumi, hum); }

int16_t recentTempes[TEMPE_HISTORY];
uint8_t recentTempesIdx = 0;
int32_t tempeSum;
int16_t lastTempe;
int16_t lastLastTempe;

void updateTemperature(int16_t temp) {
  // if lastTempe equals current one, probably it is real value, skip delta
  // filter.
  if (temp != lastTempe || lastLastTempe != lastTempe) {
    lastLastTempe = lastTempe;
    lastTempe = temp;

    // Because dht22 actually has 0.2 precision, we only use the temperature
    // only if
    // dht reading has 0.2 changes.
    int16_t cur = readTempe();
    int16_t delta = abs(cur - temp);
    if (delta < 2) {
      return;
    }

    // it is unlikly temperature changes more than 2 degrees during
    // DHT22_SAMPLE_RATE unless an error
    if (delta > 20) {
      return;
    }
  }

  tempeSum -= recentTempes[recentTempesIdx];
  recentTempes[recentTempesIdx] = temp;
  tempeSum += temp;
  if (++recentTempesIdx == TEMPE_HISTORY) {
    recentTempesIdx = 0;
  }

  setTempe(tempeSum / TEMPE_HISTORY);
}

void readTempeHumiFirstTime() {
  int16_t tempe = getTempeSetpoint();
  uint16_t humi = 500;
  if (doReadDHT22()) {
    tempe = DHT.temperature;
    humi = DHT.humidity;
  }

  for (int i = 0; i < TEMPE_HISTORY; i++) {
    recentTempes[i] = tempe;
  }
  lastTempe = lastLastTempe = tempe;
  tempeSum = tempe * TEMPE_HISTORY;

  updateTemperature(tempe);
  updateHumidity(humi);
}

void readDHT22() {
  if (!doReadDHT22()) {
    return;
  }

  updateTemperature(DHT.temperature);
  updateHumidity(DHT.humidity);
}

void setupThemeHumi(void) {
  idHumi = store::defineAnalog();
  idTempe = store::defineAnalog();

  setTempe(getTempeSetpoint());

  clock::interval(DHT22_SAMPLE_RATE, readDHT22);

  // At this time, no other modules hooks idTempe & idHumi,
  // delays inital read, to trigger interested modules.
  clock::delay(1, readTempeHumiFirstTime);
}
<commit_msg>Delay 1.5 second to read DHT22<commit_after>#include "read_temp_hum.h"
#include <dht.h>
#include "thermostat.h"
#include "tempe_control.h"

#define TEMPE_HISTORY 6  // How many temperature history value used for filter

using namespace core;

dht DHT;

// Return false if read failed.
bool doReadDHT22() {
  int chk = DHT.read22(DHT22_PIN);

  switch (chk) {
    case DHTLIB_OK:
      return true;
    case DHTLIB_ERROR_CHECKSUM:
      Serial.print(F("Checksum error,\n"));
      break;
    case DHTLIB_ERROR_TIMEOUT:
      Serial.print(F("Time out error,\n"));
      break;
    default:
      Serial.print(F("Unknown error,\n"));
      break;
  }

  return false;
}

idType idTempe, idHumi;

void setTempe(int16_t tempe) { store::setAnalog(idTempe, (uint16_t)tempe); }

void updateHumidity(uint16_t hum) { store::setAnalog(idHumi, hum); }

int16_t recentTempes[TEMPE_HISTORY];
uint8_t recentTempesIdx = 0;
int32_t tempeSum;
int16_t lastTempe;
int16_t lastLastTempe;

void updateTemperature(int16_t temp) {
  // if lastTempe equals current one, probably it is real value, skip delta
  // filter.
  if (temp != lastTempe || lastLastTempe != lastTempe) {
    lastLastTempe = lastTempe;
    lastTempe = temp;

    // Because dht22 actually has 0.2 precision, we only use the temperature
    // only if
    // dht reading has 0.2 changes.
    int16_t cur = readTempe();
    int16_t delta = abs(cur - temp);
    if (delta < 2) {
      return;
    }

    // it is unlikly temperature changes more than 2 degrees during
    // DHT22_SAMPLE_RATE unless an error
    if (delta > 20) {
      return;
    }
  }

  tempeSum -= recentTempes[recentTempesIdx];
  recentTempes[recentTempesIdx] = temp;
  tempeSum += temp;
  if (++recentTempesIdx == TEMPE_HISTORY) {
    recentTempesIdx = 0;
  }

  setTempe(tempeSum / TEMPE_HISTORY);
}

void readDHT22() {
  if (!doReadDHT22()) {
    return;
  }

  updateTemperature(DHT.temperature);
  updateHumidity(DHT.humidity);
}

void readTempeHumiFirstTime() {
  int16_t tempe = getTempeSetpoint();
  uint16_t humi = 500;
  if (doReadDHT22()) {
    tempe = DHT.temperature;
    humi = DHT.humidity;
  }

  for (int i = 0; i < TEMPE_HISTORY; i++) {
    recentTempes[i] = tempe;
  }
  lastTempe = lastLastTempe = tempe;
  tempeSum = tempe * TEMPE_HISTORY;

  updateTemperature(tempe);
  updateHumidity(humi);

  clock::interval(DHT22_SAMPLE_RATE, readDHT22);
}

void setupThemeHumi(void) {
  idHumi = store::defineAnalog();
  idTempe = store::defineAnalog();

  setTempe(getTempeSetpoint());

  // At this time, no other modules hooks idTempe & idHumi,
  // delays inital read, to trigger interested modules.
  // DHT22 datasheet said, should not read DHT22 in first second after power up.
  clock::delay(1500, readTempeHumiFirstTime);
}
<|endoftext|>


<commit_before>#include <cassert>
#include <fstream>
#include <stdexcept>
#include <iterator>
#include "reader.h"

using namespace std;

template<class T, class CharT = char, class Traits = char_traits<CharT>,
         class Distance = ptrdiff_t >
struct theresnoescapefromthisiterator
    : public iterator<input_iterator_tag, T, Distance, const T*, const T&>
{
public:
    theresnoescapefromthisiterator() = default;

    theresnoescapefromthisiterator(basic_istream<CharT, Traits> &stream) :
        stream(&stream)
    {
        stream.seekg(0, ios_base::end);
        file_size = stream.tellg();
        fill();
    }

    theresnoescapefromthisiterator &operator++()
    {
        assert(stream);
        pos += 1;
        if (pos == file_size)
            stream = NULL;
        else
            fill();
        return *this;
    }

    bool operator==(const theresnoescapefromthisiterator &rhs)
    {
        return (stream && rhs.stream) ? (pos == rhs.pos)
            : (stream == rhs.stream);
    }

    bool operator!=(const theresnoescapefromthisiterator &rhs)
    {
        return !(*this == rhs);
    }

    T operator*() const
    {
        return current.value;
    }

private:
    void fill()
    {
        stream->seekg(pos);
        for (unsigned i = 0;i != sizeof(T);++i) {
            char c;
            stream->read(&c, 1);
            current.pieces[i] = c;
        }
    }

    basic_istream<CharT, Traits> *stream = NULL;
    typename basic_istream<CharT, Traits>::pos_type pos = 0;
    typename basic_istream<CharT, Traits>::pos_type file_size;
    mutable union
    {
        T value;
        uint8_t pieces[sizeof(T)];
    } current;
};

class Reader {
public:
    Reader(istream &stream);
    theresnoescapefromthisiterator<uint8_t> begin();
    theresnoescapefromthisiterator<uint8_t> end();
private:
    theresnoescapefromthisiterator<uint8_t> begin_;
};

Reader::Reader(istream &stream)
    : begin_(stream) {
}

theresnoescapefromthisiterator<uint8_t> Reader::begin() {
    return begin_;
}

theresnoescapefromthisiterator<uint8_t> Reader::end() {
    return {};
}

map<uint8_t, unsigned int> read(string file) {
    ifstream stream(file);
    if (stream.rdstate() & ios_base::failbit)
        throw runtime_error("File do not exist");

    map<uint8_t, unsigned int> map;

    for (auto character : Reader(stream)) {
        ++map[character];
    }

    stream.close();
    return map;
}
<commit_msg>fix: file iterator was failing on empty files<commit_after>#include <cassert>
#include <fstream>
#include <stdexcept>
#include <iterator>
#include "reader.h"

using namespace std;

template<class T, class CharT = char, class Traits = char_traits<CharT>,
         class Distance = ptrdiff_t >
struct theresnoescapefromthisiterator
    : public iterator<input_iterator_tag, T, Distance, const T*, const T&>
{
public:
    theresnoescapefromthisiterator() = default;

    theresnoescapefromthisiterator(basic_istream<CharT, Traits> &stream) :
        stream(&stream)
    {
        stream.seekg(0, ios_base::end);
        file_size = stream.tellg();
        if (file_size)
            fill();
        else
            stream = NULL;
    }

    theresnoescapefromthisiterator &operator++()
    {
        assert(stream);
        pos += 1;
        if (pos == file_size)
            stream = NULL;
        else
            fill();
        return *this;
    }

    bool operator==(const theresnoescapefromthisiterator &rhs)
    {
        return (stream && rhs.stream) ? (pos == rhs.pos)
            : (stream == rhs.stream);
    }

    bool operator!=(const theresnoescapefromthisiterator &rhs)
    {
        return !(*this == rhs);
    }

    T operator*() const
    {
        return current.value;
    }

private:
    void fill()
    {
        stream->seekg(pos);
        for (unsigned i = 0;i != sizeof(T);++i) {
            char c;
            stream->read(&c, 1);
            current.pieces[i] = c;
        }
    }

    basic_istream<CharT, Traits> *stream = NULL;
    typename basic_istream<CharT, Traits>::pos_type pos = 0;
    typename basic_istream<CharT, Traits>::pos_type file_size;
    mutable union
    {
        T value;
        uint8_t pieces[sizeof(T)];
    } current;
};

class Reader {
public:
    Reader(istream &stream);
    theresnoescapefromthisiterator<uint8_t> begin();
    theresnoescapefromthisiterator<uint8_t> end();
private:
    theresnoescapefromthisiterator<uint8_t> begin_;
};

Reader::Reader(istream &stream)
    : begin_(stream) {
}

theresnoescapefromthisiterator<uint8_t> Reader::begin() {
    return begin_;
}

theresnoescapefromthisiterator<uint8_t> Reader::end() {
    return {};
}

map<uint8_t, unsigned int> read(string file) {
    ifstream stream(file);
    if (stream.rdstate() & ios_base::failbit)
        throw runtime_error("File do not exist");

    map<uint8_t, unsigned int> map;

    for (auto character : Reader(stream)) {
        ++map[character];
    }

    stream.close();
    return map;
}
<|endoftext|>


<commit_before>#include <cassert>
#include <fstream>
#include <stdexcept>
#include <iterator>
#include "reader.h"

using namespace std;

template<class T, class CharT = char, class Traits = char_traits<CharT>,
         class Distance = ptrdiff_t >
struct theresnoescapefromthisiterator
    : public iterator<input_iterator_tag, T, Distance, const T*, const T&>
{
public:
    theresnoescapefromthisiterator() = default;

    theresnoescapefromthisiterator(basic_istream<CharT, Traits> &stream) :
        stream(&stream)
    {
        stream.seekg(0, ios_base::end);
        file_size = stream.tellg();
        if (file_size)
            fill();
        else
            stream = NULL;
    }

    theresnoescapefromthisiterator &operator++()
    {
        assert(stream);
        pos += 1;
        if (pos == file_size)
            stream = NULL;
        else
            fill();
        return *this;
    }

    bool operator==(const theresnoescapefromthisiterator &rhs)
    {
        return (stream && rhs.stream) ? (pos == rhs.pos)
            : (stream == rhs.stream);
    }

    bool operator!=(const theresnoescapefromthisiterator &rhs)
    {
        return !(*this == rhs);
    }

    T operator*() const
    {
        return current.value;
    }

private:
    void fill()
    {
        stream->seekg(pos);
        for (unsigned i = 0;i != sizeof(T);++i) {
            char c;
            stream->read(&c, 1);
            current.pieces[i] = c;
        }
    }

    basic_istream<CharT, Traits> *stream = NULL;
    typename basic_istream<CharT, Traits>::pos_type pos = 0;
    typename basic_istream<CharT, Traits>::pos_type file_size;
    mutable union
    {
        T value;
        uint8_t pieces[sizeof(T)];
    } current;
};

class Reader {
public:
    Reader(istream &stream);
    theresnoescapefromthisiterator<uint8_t> begin();
    theresnoescapefromthisiterator<uint8_t> end();
private:
    theresnoescapefromthisiterator<uint8_t> begin_;
};

Reader::Reader(istream &stream)
    : begin_(stream) {
}

theresnoescapefromthisiterator<uint8_t> Reader::begin() {
    return begin_;
}

theresnoescapefromthisiterator<uint8_t> Reader::end() {
    return {};
}

map<uint8_t, unsigned int> read(string file) {
    ifstream stream(file);
    if (stream.rdstate() & ios_base::failbit)
        throw runtime_error("File do not exist");

    map<uint8_t, unsigned int> map;

    for (auto character : Reader(stream)) {
        ++map[character];
    }

    stream.close();
    return map;
}
<commit_msg>Fixes commit f732a598e345d67d624aa837a41ec23edaa62f59<commit_after>#include <cassert>
#include <fstream>
#include <stdexcept>
#include <iterator>
#include "reader.h"

using namespace std;

template<class T, class CharT = char, class Traits = char_traits<CharT>,
         class Distance = ptrdiff_t >
struct theresnoescapefromthisiterator
    : public iterator<input_iterator_tag, T, Distance, const T*, const T&>
{
public:
    theresnoescapefromthisiterator() = default;

    theresnoescapefromthisiterator(basic_istream<CharT, Traits> &stream) :
        stream(&stream)
    {
        stream.seekg(0, ios_base::end);
        file_size = stream.tellg();
        if (file_size)
            fill();
        else
            this->stream = NULL;
    }

    theresnoescapefromthisiterator &operator++()
    {
        assert(stream);
        pos += 1;
        if (pos == file_size)
            stream = NULL;
        else
            fill();
        return *this;
    }

    bool operator==(const theresnoescapefromthisiterator &rhs)
    {
        return (stream && rhs.stream) ? (pos == rhs.pos)
            : (stream == rhs.stream);
    }

    bool operator!=(const theresnoescapefromthisiterator &rhs)
    {
        return !(*this == rhs);
    }

    T operator*() const
    {
        return current.value;
    }

private:
    void fill()
    {
        stream->seekg(pos);
        for (unsigned i = 0;i != sizeof(T);++i) {
            char c;
            stream->read(&c, 1);
            current.pieces[i] = c;
        }
    }

    basic_istream<CharT, Traits> *stream = NULL;
    typename basic_istream<CharT, Traits>::pos_type pos = 0;
    typename basic_istream<CharT, Traits>::pos_type file_size;
    mutable union
    {
        T value;
        uint8_t pieces[sizeof(T)];
    } current;
};

class Reader {
public:
    Reader(istream &stream);
    theresnoescapefromthisiterator<uint8_t> begin();
    theresnoescapefromthisiterator<uint8_t> end();
private:
    theresnoescapefromthisiterator<uint8_t> begin_;
};

Reader::Reader(istream &stream)
    : begin_(stream) {
}

theresnoescapefromthisiterator<uint8_t> Reader::begin() {
    return begin_;
}

theresnoescapefromthisiterator<uint8_t> Reader::end() {
    return {};
}

map<uint8_t, unsigned int> read(string file) {
    ifstream stream(file);
    if (stream.rdstate() & ios_base::failbit)
        throw runtime_error("File do not exist");

    map<uint8_t, unsigned int> map;

    for (auto character : Reader(stream)) {
        ++map[character];
    }

    stream.close();
    return map;
}
<|endoftext|>


<commit_before>#include <unordered_set>
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Parse/ParseAST.h>
#include <clang/AST/Decl.h>
#include <clang/AST/DeclGroup.h>
#include <clang/AST/Type.h>
#include <clang/AST/PrettyPrinter.h>
#include "c-import.h"
#include "typecheck.h"
#include "../ast/type.h"
#include "../ast/decl.h"

namespace {

clang::PrintingPolicy printingPolicy{clang::LangOptions()};

/** Prints the message to stderr if it hasn't been printed yet. */
void warnOnce(const llvm::Twine& message) {
    static std::unordered_set<std::string> printedMessages;
    llvm::SmallVector<char, 64> buffer;
    if (printedMessages.count(message.toStringRef(buffer)) != 0) return;
    llvm::errs() << "WARNING: " << *printedMessages.emplace(message.str()).first << '\n';
}

Type toDelta(clang::QualType qualtype) {
    auto& type = *qualtype.getTypePtr();
    switch (type.getTypeClass()) {
        case clang::Type::Pointer: {
            auto pointeeType = llvm::cast<clang::PointerType>(type).getPointeeType();
            return Type(PtrType(llvm::make_unique<Type>(toDelta(pointeeType))));
        }
        case clang::Type::Builtin:
            switch (llvm::cast<clang::BuiltinType>(type).getKind()) {
                case clang::BuiltinType::Void:  return Type(BasicType{"void"});
                case clang::BuiltinType::Bool:  return Type(BasicType{"bool"});
                case clang::BuiltinType::Char_S:
                case clang::BuiltinType::Char_U:return Type(BasicType{"char"});
                case clang::BuiltinType::Int:   return Type(BasicType{"int"});
                case clang::BuiltinType::UInt:  return Type(BasicType{"uint"});
                default:
                    auto name = llvm::cast<clang::BuiltinType>(type).getName(printingPolicy);
                    warnOnce("Builtin type '" + name + "' not handled");
                    return Type(BasicType{"int"});
            }
            return Type(BasicType{llvm::cast<clang::BuiltinType>(type).getName(printingPolicy)});
        case clang::Type::Typedef:
            return toDelta(llvm::cast<clang::TypedefType>(type).desugar());
        case clang::Type::Elaborated:
            return toDelta(llvm::cast<clang::ElaboratedType>(type).getNamedType());
        case clang::Type::Record:
            return Type(BasicType{llvm::cast<clang::RecordType>(type).getDecl()->getName()});
        default:
            warnOnce(llvm::Twine(type.getTypeClassName()) + " not handled");
            return Type(BasicType{"int"});
    }
}

FuncDecl toDelta(const clang::FunctionDecl& decl) {
    std::vector<ParamDecl> params;
    for (auto* param : decl.parameters()) {
        params.emplace_back(ParamDecl{"", toDelta(param->getType()), param->getNameAsString()});
    }
    return FuncDecl{decl.getNameAsString(), std::move(params), toDelta(decl.getReturnType())};
}

class CToDeltaConverter : public clang::ASTConsumer {
public:
    bool HandleTopLevelDecl(clang::DeclGroupRef declGroup) final override {
        for (clang::Decl* decl : declGroup) {
            switch (decl->getKind()) {
                case clang::Decl::Function:
                    addToSymbolTable(toDelta(llvm::cast<clang::FunctionDecl>(*decl)));
                    break;
                default:
                    break;
            }
        }
        return true; // continue parsing
    }
};

// FIXME: Temporary hack for finding Clang builtin includes.
// See http://clang.llvm.org/docs/FAQ.html#i-get-errors-about-some-headers-being-missing-stddef-h-stdarg-h
std::string getClangBuiltinIncludePath() {
    char path[64];
    std::shared_ptr<FILE> f(popen("dirname $(dirname $(which clang))", "r"), pclose);
    if (!f || fscanf(f.get(), "%63s", path) != 1) return "";

    char version[6];
    f.reset(popen("clang --version", "r"), pclose);
    if (!f || fscanf(f.get(), "clang version %5s", version) != 1) return "";

    return std::string(path) + "/lib/clang/" + version + "/include";
}

} // anonymous namespace

void importCHeader(llvm::StringRef headerName) {
    clang::CompilerInstance ci;
    clang::DiagnosticOptions diagnosticOptions;
    ci.createDiagnostics();

    std::shared_ptr<clang::TargetOptions> pto = std::make_shared<clang::TargetOptions>();
    pto->Triple = llvm::sys::getDefaultTargetTriple();
    clang::TargetInfo* pti = clang::TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto);
    ci.setTarget(pti);

    ci.createFileManager();
    ci.createSourceManager(ci.getFileManager());

    ci.getHeaderSearchOpts().AddPath("/usr/include",       clang::frontend::System, false, false);
    ci.getHeaderSearchOpts().AddPath("/usr/local/include", clang::frontend::System, false, false);

    std::string clangBuiltinIncludePath = getClangBuiltinIncludePath();
    if (!clangBuiltinIncludePath.empty()) {
        ci.getHeaderSearchOpts().AddPath(clangBuiltinIncludePath, clang::frontend::System, false, false);
    } else {
        llvm::errs() << "warning: clang not found, importing certain headers might not work\n";
    }

    ci.createPreprocessor(clang::TU_Complete);
    ci.getPreprocessorOpts().UsePredefines = false;

    ci.setASTConsumer(llvm::make_unique<CToDeltaConverter>());
    ci.createASTContext();

    const clang::DirectoryLookup* curDir = nullptr;
    const clang::FileEntry* pFile = ci.getPreprocessor().getHeaderSearchInfo().LookupFile(
        headerName, {}, false, nullptr, curDir, {}, nullptr, nullptr, nullptr, nullptr);
    if (!pFile) {
        llvm::errs() << "error: couldn't find header '" << headerName << "'\n";
        abort();
    }

    ci.getSourceManager().setMainFileID(ci.getSourceManager().createFileID(
        pFile, clang::SourceLocation(), clang::SrcMgr::C_System));
    ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(), &ci.getPreprocessor());
    clang::ParseAST(ci.getPreprocessor(), &ci.getASTConsumer(), ci.getASTContext());
    ci.getDiagnosticClient().EndSourceFile();
}
<commit_msg>[c-import] initialize Clang builtins<commit_after>#include <unordered_set>
#include <clang/Basic/TargetInfo.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Parse/ParseAST.h>
#include <clang/AST/Decl.h>
#include <clang/AST/DeclGroup.h>
#include <clang/AST/Type.h>
#include <clang/AST/PrettyPrinter.h>
#include "c-import.h"
#include "typecheck.h"
#include "../ast/type.h"
#include "../ast/decl.h"

namespace {

clang::PrintingPolicy printingPolicy{clang::LangOptions()};

/** Prints the message to stderr if it hasn't been printed yet. */
void warnOnce(const llvm::Twine& message) {
    static std::unordered_set<std::string> printedMessages;
    llvm::SmallVector<char, 64> buffer;
    if (printedMessages.count(message.toStringRef(buffer)) != 0) return;
    llvm::errs() << "WARNING: " << *printedMessages.emplace(message.str()).first << '\n';
}

Type toDelta(clang::QualType qualtype) {
    auto& type = *qualtype.getTypePtr();
    switch (type.getTypeClass()) {
        case clang::Type::Pointer: {
            auto pointeeType = llvm::cast<clang::PointerType>(type).getPointeeType();
            return Type(PtrType(llvm::make_unique<Type>(toDelta(pointeeType))));
        }
        case clang::Type::Builtin:
            switch (llvm::cast<clang::BuiltinType>(type).getKind()) {
                case clang::BuiltinType::Void:  return Type(BasicType{"void"});
                case clang::BuiltinType::Bool:  return Type(BasicType{"bool"});
                case clang::BuiltinType::Char_S:
                case clang::BuiltinType::Char_U:return Type(BasicType{"char"});
                case clang::BuiltinType::Int:   return Type(BasicType{"int"});
                case clang::BuiltinType::UInt:  return Type(BasicType{"uint"});
                default:
                    auto name = llvm::cast<clang::BuiltinType>(type).getName(printingPolicy);
                    warnOnce("Builtin type '" + name + "' not handled");
                    return Type(BasicType{"int"});
            }
            return Type(BasicType{llvm::cast<clang::BuiltinType>(type).getName(printingPolicy)});
        case clang::Type::Typedef:
            return toDelta(llvm::cast<clang::TypedefType>(type).desugar());
        case clang::Type::Elaborated:
            return toDelta(llvm::cast<clang::ElaboratedType>(type).getNamedType());
        case clang::Type::Record:
            return Type(BasicType{llvm::cast<clang::RecordType>(type).getDecl()->getName()});
        default:
            warnOnce(llvm::Twine(type.getTypeClassName()) + " not handled");
            return Type(BasicType{"int"});
    }
}

FuncDecl toDelta(const clang::FunctionDecl& decl) {
    std::vector<ParamDecl> params;
    for (auto* param : decl.parameters()) {
        params.emplace_back(ParamDecl{"", toDelta(param->getType()), param->getNameAsString()});
    }
    return FuncDecl{decl.getNameAsString(), std::move(params), toDelta(decl.getReturnType())};
}

class CToDeltaConverter : public clang::ASTConsumer {
public:
    bool HandleTopLevelDecl(clang::DeclGroupRef declGroup) final override {
        for (clang::Decl* decl : declGroup) {
            switch (decl->getKind()) {
                case clang::Decl::Function:
                    addToSymbolTable(toDelta(llvm::cast<clang::FunctionDecl>(*decl)));
                    break;
                default:
                    break;
            }
        }
        return true; // continue parsing
    }
};

// FIXME: Temporary hack for finding Clang builtin includes.
// See http://clang.llvm.org/docs/FAQ.html#i-get-errors-about-some-headers-being-missing-stddef-h-stdarg-h
std::string getClangBuiltinIncludePath() {
    char path[64];
    std::shared_ptr<FILE> f(popen("dirname $(dirname $(which clang))", "r"), pclose);
    if (!f || fscanf(f.get(), "%63s", path) != 1) return "";

    char version[6];
    f.reset(popen("clang --version", "r"), pclose);
    if (!f || fscanf(f.get(), "clang version %5s", version) != 1) return "";

    return std::string(path) + "/lib/clang/" + version + "/include";
}

} // anonymous namespace

void importCHeader(llvm::StringRef headerName) {
    clang::CompilerInstance ci;
    clang::DiagnosticOptions diagnosticOptions;
    ci.createDiagnostics();

    std::shared_ptr<clang::TargetOptions> pto = std::make_shared<clang::TargetOptions>();
    pto->Triple = llvm::sys::getDefaultTargetTriple();
    clang::TargetInfo* pti = clang::TargetInfo::CreateTargetInfo(ci.getDiagnostics(), pto);
    ci.setTarget(pti);

    ci.createFileManager();
    ci.createSourceManager(ci.getFileManager());

    ci.getHeaderSearchOpts().AddPath("/usr/include",       clang::frontend::System, false, false);
    ci.getHeaderSearchOpts().AddPath("/usr/local/include", clang::frontend::System, false, false);

    std::string clangBuiltinIncludePath = getClangBuiltinIncludePath();
    if (!clangBuiltinIncludePath.empty()) {
        ci.getHeaderSearchOpts().AddPath(clangBuiltinIncludePath, clang::frontend::System, false, false);
    } else {
        llvm::errs() << "warning: clang not found, importing certain headers might not work\n";
    }

    ci.createPreprocessor(clang::TU_Complete);
    auto& pp = ci.getPreprocessor();
    pp.getBuiltinInfo().initializeBuiltins(pp.getIdentifierTable(), pp.getLangOpts());

    ci.setASTConsumer(llvm::make_unique<CToDeltaConverter>());
    ci.createASTContext();

    const clang::DirectoryLookup* curDir = nullptr;
    const clang::FileEntry* pFile = ci.getPreprocessor().getHeaderSearchInfo().LookupFile(
        headerName, {}, false, nullptr, curDir, {}, nullptr, nullptr, nullptr, nullptr);
    if (!pFile) {
        llvm::errs() << "error: couldn't find header '" << headerName << "'\n";
        abort();
    }

    ci.getSourceManager().setMainFileID(ci.getSourceManager().createFileID(
        pFile, clang::SourceLocation(), clang::SrcMgr::C_System));
    ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(), &ci.getPreprocessor());
    clang::ParseAST(ci.getPreprocessor(), &ci.getASTConsumer(), ci.getASTContext());
    ci.getDiagnosticClient().EndSourceFile();
}
<|endoftext|>