<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "AbstractFramebuffer.h"

#include "BufferImage.h"
#include "Context.h"
#include "Extensions.h"
#include "Image.h"

#include "Implementation/FramebufferState.h"
#include "Implementation/State.h"

namespace Magnum {

AbstractFramebuffer::CheckStatusImplementation AbstractFramebuffer::checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault;

AbstractFramebuffer::ReadImplementation AbstractFramebuffer::readImplementation = &AbstractFramebuffer::readImplementationDefault;

AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault;
AbstractFramebuffer::DrawBufferImplementation AbstractFramebuffer::drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
AbstractFramebuffer::ReadBufferImplementation AbstractFramebuffer::readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;

#ifdef MAGNUM_TARGET_GLES2
FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw;
FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw;
#endif

void AbstractFramebuffer::bind(FramebufferTarget target) {
    bindInternal(target);
    setViewportInternal();
}

void AbstractFramebuffer::bindInternal(FramebufferTarget target) {
    Implementation::FramebufferState* state = Context::current()->state().framebuffer;

    /* If already bound, done, otherwise update tracked state */
    if(target == FramebufferTarget::Read) {
        if(state->readBinding == _id) return;
        state->readBinding = _id;
    } else if(target == FramebufferTarget::Draw) {
        if(state->drawBinding == _id) return;
        state->drawBinding = _id;
    } else if(target == FramebufferTarget::ReadDraw) {
        if(state->readBinding == _id && state->drawBinding == _id) return;
        state->readBinding = state->drawBinding = _id;
    } else CORRADE_ASSERT_UNREACHABLE();

    glBindFramebuffer(static_cast<GLenum>(target), _id);
}

FramebufferTarget AbstractFramebuffer::bindInternal() {
    Implementation::FramebufferState* state = Context::current()->state().framebuffer;

    /* Return target to which the framebuffer is already bound */
    if(state->readBinding == _id && state->drawBinding == _id)
        return FramebufferTarget::ReadDraw;
    if(state->readBinding == _id)
        return FramebufferTarget::Read;
    if(state->drawBinding == _id)
        return FramebufferTarget::Draw;

    /* Or bind it, if not already */
    state->readBinding = _id;

    #ifndef MAGNUM_TARGET_GLES2
    glBindFramebuffer(GLenum(FramebufferTarget::Read), _id);
    return FramebufferTarget::Read;
    #else
    if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
    glBindFramebuffer(GLenum(readTarget), _id);
    return readTarget;
    #endif
}

void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Rectanglei& sourceRectangle, const Rectanglei& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter) {
    source.bindInternal(FramebufferTarget::Read);
    destination.bindInternal(FramebufferTarget::Draw);
    /** @todo Get some extension wrangler instead to avoid undeclared glBlitFramebuffer() on ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    glBlitFramebuffer(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), static_cast<GLbitfield>(mask), static_cast<GLenum>(filter));
    #else
    static_cast<void>(sourceRectangle);
    static_cast<void>(destinationRectangle);
    static_cast<void>(mask);
    static_cast<void>(filter);
    #endif
}

AbstractFramebuffer& AbstractFramebuffer::setViewport(const Rectanglei& rectangle) {
    _viewport = rectangle;

    /* Update the viewport if the framebuffer is currently bound */
    if(Context::current()->state().framebuffer->drawBinding == _id)
        setViewportInternal();

    return *this;
}

void AbstractFramebuffer::setViewportInternal() {
    Implementation::FramebufferState* state = Context::current()->state().framebuffer;

    CORRADE_INTERNAL_ASSERT(state->drawBinding == _id);

    /* Already up-to-date, nothing to do */
    if(state->viewport == _viewport)
        return;

    /* Update the state and viewport */
    state->viewport = _viewport;
    glViewport(_viewport.left(), _viewport.bottom(), _viewport.width(), _viewport.height());
}

void AbstractFramebuffer::clear(FramebufferClearMask mask) {
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Draw);
    #else
    bindInternal(drawTarget);
    #endif
    glClear(static_cast<GLbitfield>(mask));
}

void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Image2D& image) {
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Read);
    #else
    bindInternal(readTarget);
    #endif
    const std::size_t dataSize = image.pixelSize()*size.product();
    char* const data = new char[dataSize];
    readImplementation(offset, size, image.format(), image.type(), dataSize, data);
    image.setData(image.format(), image.type(), size, data);
}

#ifndef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, BufferImage2D& image, Buffer::Usage usage) {
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Read);
    #else
    bindInternal(readTarget);
    #endif
    /* If the buffer doesn't have sufficient size, resize it */
    /** @todo Explicitly reset also when buffer usage changes */
    if(image.size() != size)
        image.setData(size, image.format(), image.type(), nullptr, usage);

    image.buffer().bind(Buffer::Target::PixelPack);
    /** @todo De-duplicate buffer size computation */
    readImplementation(offset, size, image.format(), image.type(), image.pixelSize()*size.product(), nullptr);
}
#endif

void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attachments) {
    /** @todo Re-enable when extension wrangler is available for ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    glInvalidateFramebuffer(GLenum(bindInternal()), count, attachments);
    #else
    //glDiscardFramebufferEXT(GLenum(bindInternal()), count, attachments);
    static_cast<void>(count);
    static_cast<void>(attachments);
    #endif
}

void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attachments, const Rectanglei& rectangle) {
    /** @todo Re-enable when extension wrangler is available for ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    glInvalidateSubFramebuffer(GLenum(bindInternal()), count, attachments, rectangle.left(), rectangle.bottom(), rectangle.width(), rectangle.height());
    #else
    //glDiscardSubFramebufferEXT(GLenum(bindInternal()), count, attachments, rectangle.left(), rectangle.bottom(), rectangle.width(), rectangle.height());
    static_cast<void>(count);
    static_cast<void>(attachments);
    static_cast<void>(rectangle);
    #endif
}

void AbstractFramebuffer::initializeContextBasedFunctionality(Context& context) {
    #ifndef MAGNUM_TARGET_GLES
    if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";

        checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA;
        drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA;
        drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA;
        readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA;
    }
    #endif

    #ifdef MAGNUM_TARGET_GLES2
    /* Optimistically set separate binding targets and check if one of the
       extensions providing them is available */
    readTarget = FramebufferTarget::Read;
    drawTarget = FramebufferTarget::Draw;

    if(context->isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>())
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::ANGLE::framebuffer_blit::string() << "features";

    else if(context->isExtensionSupported<Extensions::GL::APPLE::framebuffer_multisample>())
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::APPLE::framebuffer_multisample::string() << "features";

    else if(context->isExtensionSupported<Extensions::GL::NV::framebuffer_blit>())
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_blit::string() << "features";

    /* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these
       enums. However, on my system only NV_framebuffer_multisample is
       supported, but NV_framebuffer_blit isn't. I will hold my breath and
       assume these enums are available. */
    else if(context->isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>())
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_multisample::string() << "features";

    /* If no such extension is available, reset back to unified target */
    else readTarget = drawTarget = FramebufferTarget::ReadDraw;
    #endif

    #ifndef MAGNUM_TARGET_GLES3
    #ifndef MAGNUM_TARGET_GLES
    if(context.isExtensionSupported<Extensions::GL::ARB::robustness>())
    #else
    if(context.isExtensionSupported<Extensions::GL::EXT::robustness>())
    #endif
    {
        #ifndef MAGNUM_TARGET_GLES
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::ARB::robustness::string() << "features";
        #else
        //Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::robustness::string() << "features";
        #endif

        /** @todo Enable when extension wrangler for ES is available */
        #ifndef MAGNUM_TARGET_GLES
        readImplementation = &AbstractFramebuffer::readImplementationRobustness;
        #endif
    }
    #else
    static_cast<void>(context);
    #endif
}

GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) {
    bindInternal(target);
    return glCheckFramebufferStatus(GLenum(target));
}

#ifndef MAGNUM_TARGET_GLES
GLenum AbstractFramebuffer::checkStatusImplementationDSA(const FramebufferTarget target) {
    return glCheckNamedFramebufferStatusEXT(_id, GLenum(target));
}
#endif

void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers) {
    /** @todo Re-enable when extension wrangler is available for ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Draw);
    #else
    bindInternal(drawTarget);
    #endif
    glDrawBuffers(count, buffers);
    #else
    static_cast<void>(count);
    static_cast<void>(buffers);
    #endif
}

#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers) {
    glFramebufferDrawBuffersEXT(_id, count, buffers);
}
#endif

void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) {
    /** @todo Re-enable when extension wrangler is available for ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Draw);
    #else
    bindInternal(drawTarget);
    #endif
    #ifndef MAGNUM_TARGET_GLES3
    glDrawBuffer(buffer);
    #else
    glDrawBuffers(1, &buffer);
    #endif
    #else
    static_cast<void>(buffer);
    #endif
}

#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBufferImplementationDSA(GLenum buffer) {
    glFramebufferDrawBufferEXT(_id, buffer);
}
#endif

void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
    /** @todo Get some extension wrangler instead to avoid undeclared glReadBuffer() on ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Read);
    #else
    bindInternal(readTarget);
    #endif
    glReadBuffer(buffer);
    #else
    static_cast<void>(buffer);
    #endif
}

#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::readBufferImplementationDSA(GLenum buffer) {
    glFramebufferReadBufferEXT(_id, buffer);
}
#endif

void AbstractFramebuffer::readImplementationDefault(const Vector2i& offset, const Vector2i& size, const ImageFormat format, const ImageType type, const std::size_t, GLvoid* const data) {
    glReadPixels(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data);
}

#ifndef MAGNUM_TARGET_GLES3
void AbstractFramebuffer::readImplementationRobustness(const Vector2i& offset, const Vector2i& size, const ImageFormat format, const ImageType type, const std::size_t dataSize, GLvoid* const data) {
    /** @todo Enable when extension wrangler for ES is available */
    #ifndef MAGNUM_TARGET_GLES
    glReadnPixelsARB(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), dataSize, data);
    #else
    CORRADE_INTERNAL_ASSERT(false);
    //glReadnPixelsEXT(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data);
    static_cast<void>(offset);
    static_cast<void>(size);
    static_cast<void>(format);
    static_cast<void>(type);
    static_cast<void>(dataSize);
    static_cast<void>(data);
    #endif
}
#endif

}
<commit_msg>OpenGL ES build fixes.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "AbstractFramebuffer.h"

#include "BufferImage.h"
#include "Context.h"
#include "Extensions.h"
#include "Image.h"

#include "Implementation/FramebufferState.h"
#include "Implementation/State.h"

namespace Magnum {

AbstractFramebuffer::CheckStatusImplementation AbstractFramebuffer::checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDefault;

AbstractFramebuffer::ReadImplementation AbstractFramebuffer::readImplementation = &AbstractFramebuffer::readImplementationDefault;

AbstractFramebuffer::DrawBuffersImplementation AbstractFramebuffer::drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDefault;
AbstractFramebuffer::DrawBufferImplementation AbstractFramebuffer::drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDefault;
AbstractFramebuffer::ReadBufferImplementation AbstractFramebuffer::readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDefault;

#ifdef MAGNUM_TARGET_GLES2
FramebufferTarget AbstractFramebuffer::readTarget = FramebufferTarget::ReadDraw;
FramebufferTarget AbstractFramebuffer::drawTarget = FramebufferTarget::ReadDraw;
#endif

void AbstractFramebuffer::bind(FramebufferTarget target) {
    bindInternal(target);
    setViewportInternal();
}

void AbstractFramebuffer::bindInternal(FramebufferTarget target) {
    Implementation::FramebufferState* state = Context::current()->state().framebuffer;

    /* If already bound, done, otherwise update tracked state */
    if(target == FramebufferTarget::Read) {
        if(state->readBinding == _id) return;
        state->readBinding = _id;
    } else if(target == FramebufferTarget::Draw) {
        if(state->drawBinding == _id) return;
        state->drawBinding = _id;
    } else if(target == FramebufferTarget::ReadDraw) {
        if(state->readBinding == _id && state->drawBinding == _id) return;
        state->readBinding = state->drawBinding = _id;
    } else CORRADE_ASSERT_UNREACHABLE();

    glBindFramebuffer(static_cast<GLenum>(target), _id);
}

FramebufferTarget AbstractFramebuffer::bindInternal() {
    Implementation::FramebufferState* state = Context::current()->state().framebuffer;

    /* Return target to which the framebuffer is already bound */
    if(state->readBinding == _id && state->drawBinding == _id)
        return FramebufferTarget::ReadDraw;
    if(state->readBinding == _id)
        return FramebufferTarget::Read;
    if(state->drawBinding == _id)
        return FramebufferTarget::Draw;

    /* Or bind it, if not already */
    state->readBinding = _id;

    #ifndef MAGNUM_TARGET_GLES2
    glBindFramebuffer(GLenum(FramebufferTarget::Read), _id);
    return FramebufferTarget::Read;
    #else
    if(readTarget == FramebufferTarget::ReadDraw) state->drawBinding = _id;
    glBindFramebuffer(GLenum(readTarget), _id);
    return readTarget;
    #endif
}

void AbstractFramebuffer::blit(AbstractFramebuffer& source, AbstractFramebuffer& destination, const Rectanglei& sourceRectangle, const Rectanglei& destinationRectangle, FramebufferBlitMask mask, FramebufferBlitFilter filter) {
    source.bindInternal(FramebufferTarget::Read);
    destination.bindInternal(FramebufferTarget::Draw);
    /** @todo Get some extension wrangler instead to avoid undeclared glBlitFramebuffer() on ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    glBlitFramebuffer(sourceRectangle.left(), sourceRectangle.bottom(), sourceRectangle.right(), sourceRectangle.top(), destinationRectangle.left(), destinationRectangle.bottom(), destinationRectangle.right(), destinationRectangle.top(), static_cast<GLbitfield>(mask), static_cast<GLenum>(filter));
    #else
    static_cast<void>(sourceRectangle);
    static_cast<void>(destinationRectangle);
    static_cast<void>(mask);
    static_cast<void>(filter);
    #endif
}

AbstractFramebuffer& AbstractFramebuffer::setViewport(const Rectanglei& rectangle) {
    _viewport = rectangle;

    /* Update the viewport if the framebuffer is currently bound */
    if(Context::current()->state().framebuffer->drawBinding == _id)
        setViewportInternal();

    return *this;
}

void AbstractFramebuffer::setViewportInternal() {
    Implementation::FramebufferState* state = Context::current()->state().framebuffer;

    CORRADE_INTERNAL_ASSERT(state->drawBinding == _id);

    /* Already up-to-date, nothing to do */
    if(state->viewport == _viewport)
        return;

    /* Update the state and viewport */
    state->viewport = _viewport;
    glViewport(_viewport.left(), _viewport.bottom(), _viewport.width(), _viewport.height());
}

void AbstractFramebuffer::clear(FramebufferClearMask mask) {
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Draw);
    #else
    bindInternal(drawTarget);
    #endif
    glClear(static_cast<GLbitfield>(mask));
}

void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, Image2D& image) {
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Read);
    #else
    bindInternal(readTarget);
    #endif
    const std::size_t dataSize = image.pixelSize()*size.product();
    char* const data = new char[dataSize];
    readImplementation(offset, size, image.format(), image.type(), dataSize, data);
    image.setData(image.format(), image.type(), size, data);
}

#ifndef MAGNUM_TARGET_GLES2
void AbstractFramebuffer::read(const Vector2i& offset, const Vector2i& size, BufferImage2D& image, Buffer::Usage usage) {
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Read);
    #else
    bindInternal(readTarget);
    #endif
    /* If the buffer doesn't have sufficient size, resize it */
    /** @todo Explicitly reset also when buffer usage changes */
    if(image.size() != size)
        image.setData(size, image.format(), image.type(), nullptr, usage);

    image.buffer().bind(Buffer::Target::PixelPack);
    /** @todo De-duplicate buffer size computation */
    readImplementation(offset, size, image.format(), image.type(), image.pixelSize()*size.product(), nullptr);
}
#endif

void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attachments) {
    /** @todo Re-enable when extension wrangler is available for ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    glInvalidateFramebuffer(GLenum(bindInternal()), count, attachments);
    #else
    //glDiscardFramebufferEXT(GLenum(bindInternal()), count, attachments);
    static_cast<void>(count);
    static_cast<void>(attachments);
    #endif
}

void AbstractFramebuffer::invalidateImplementation(GLsizei count, GLenum* attachments, const Rectanglei& rectangle) {
    /** @todo Re-enable when extension wrangler is available for ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    glInvalidateSubFramebuffer(GLenum(bindInternal()), count, attachments, rectangle.left(), rectangle.bottom(), rectangle.width(), rectangle.height());
    #else
    //glDiscardSubFramebufferEXT(GLenum(bindInternal()), count, attachments, rectangle.left(), rectangle.bottom(), rectangle.width(), rectangle.height());
    static_cast<void>(count);
    static_cast<void>(attachments);
    static_cast<void>(rectangle);
    #endif
}

void AbstractFramebuffer::initializeContextBasedFunctionality(Context& context) {
    #ifndef MAGNUM_TARGET_GLES
    if(context.isExtensionSupported<Extensions::GL::EXT::direct_state_access>()) {
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features";

        checkStatusImplementation = &AbstractFramebuffer::checkStatusImplementationDSA;
        drawBuffersImplementation = &AbstractFramebuffer::drawBuffersImplementationDSA;
        drawBufferImplementation = &AbstractFramebuffer::drawBufferImplementationDSA;
        readBufferImplementation = &AbstractFramebuffer::readBufferImplementationDSA;
    }
    #endif

    #ifdef MAGNUM_TARGET_GLES2
    /* Optimistically set separate binding targets and check if one of the
       extensions providing them is available */
    readTarget = FramebufferTarget::Read;
    drawTarget = FramebufferTarget::Draw;

    if(context.isExtensionSupported<Extensions::GL::ANGLE::framebuffer_blit>())
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::ANGLE::framebuffer_blit::string() << "features";

    else if(context.isExtensionSupported<Extensions::GL::APPLE::framebuffer_multisample>())
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::APPLE::framebuffer_multisample::string() << "features";

    else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_blit>())
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_blit::string() << "features";

    /* NV_framebuffer_multisample requires NV_framebuffer_blit, which has these
       enums. However, on my system only NV_framebuffer_multisample is
       supported, but NV_framebuffer_blit isn't. I will hold my breath and
       assume these enums are available. */
    else if(context.isExtensionSupported<Extensions::GL::NV::framebuffer_multisample>())
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::NV::framebuffer_multisample::string() << "features";

    /* If no such extension is available, reset back to unified target */
    else readTarget = drawTarget = FramebufferTarget::ReadDraw;
    #endif

    #ifndef MAGNUM_TARGET_GLES3
    #ifndef MAGNUM_TARGET_GLES
    if(context.isExtensionSupported<Extensions::GL::ARB::robustness>())
    #else
    if(context.isExtensionSupported<Extensions::GL::EXT::robustness>())
    #endif
    {
        #ifndef MAGNUM_TARGET_GLES
        Debug() << "AbstractFramebuffer: using" << Extensions::GL::ARB::robustness::string() << "features";
        #else
        //Debug() << "AbstractFramebuffer: using" << Extensions::GL::EXT::robustness::string() << "features";
        #endif

        /** @todo Enable when extension wrangler for ES is available */
        #ifndef MAGNUM_TARGET_GLES
        readImplementation = &AbstractFramebuffer::readImplementationRobustness;
        #endif
    }
    #else
    static_cast<void>(context);
    #endif
}

GLenum AbstractFramebuffer::checkStatusImplementationDefault(const FramebufferTarget target) {
    bindInternal(target);
    return glCheckFramebufferStatus(GLenum(target));
}

#ifndef MAGNUM_TARGET_GLES
GLenum AbstractFramebuffer::checkStatusImplementationDSA(const FramebufferTarget target) {
    return glCheckNamedFramebufferStatusEXT(_id, GLenum(target));
}
#endif

void AbstractFramebuffer::drawBuffersImplementationDefault(GLsizei count, const GLenum* buffers) {
    /** @todo Re-enable when extension wrangler is available for ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Draw);
    #else
    bindInternal(drawTarget);
    #endif
    glDrawBuffers(count, buffers);
    #else
    static_cast<void>(count);
    static_cast<void>(buffers);
    #endif
}

#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBuffersImplementationDSA(GLsizei count, const GLenum* buffers) {
    glFramebufferDrawBuffersEXT(_id, count, buffers);
}
#endif

void AbstractFramebuffer::drawBufferImplementationDefault(GLenum buffer) {
    /** @todo Re-enable when extension wrangler is available for ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Draw);
    #else
    bindInternal(drawTarget);
    #endif
    #ifndef MAGNUM_TARGET_GLES3
    glDrawBuffer(buffer);
    #else
    glDrawBuffers(1, &buffer);
    #endif
    #else
    static_cast<void>(buffer);
    #endif
}

#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::drawBufferImplementationDSA(GLenum buffer) {
    glFramebufferDrawBufferEXT(_id, buffer);
}
#endif

void AbstractFramebuffer::readBufferImplementationDefault(GLenum buffer) {
    /** @todo Get some extension wrangler instead to avoid undeclared glReadBuffer() on ES2 */
    #ifndef MAGNUM_TARGET_GLES2
    #ifndef MAGNUM_TARGET_GLES2
    bindInternal(FramebufferTarget::Read);
    #else
    bindInternal(readTarget);
    #endif
    glReadBuffer(buffer);
    #else
    static_cast<void>(buffer);
    #endif
}

#ifndef MAGNUM_TARGET_GLES
void AbstractFramebuffer::readBufferImplementationDSA(GLenum buffer) {
    glFramebufferReadBufferEXT(_id, buffer);
}
#endif

void AbstractFramebuffer::readImplementationDefault(const Vector2i& offset, const Vector2i& size, const ImageFormat format, const ImageType type, const std::size_t, GLvoid* const data) {
    glReadPixels(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data);
}

#ifndef MAGNUM_TARGET_GLES3
void AbstractFramebuffer::readImplementationRobustness(const Vector2i& offset, const Vector2i& size, const ImageFormat format, const ImageType type, const std::size_t dataSize, GLvoid* const data) {
    /** @todo Enable when extension wrangler for ES is available */
    #ifndef MAGNUM_TARGET_GLES
    glReadnPixelsARB(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), dataSize, data);
    #else
    CORRADE_INTERNAL_ASSERT(false);
    //glReadnPixelsEXT(offset.x(), offset.y(), size.x(), size.y(), static_cast<GLenum>(format), static_cast<GLenum>(type), data);
    static_cast<void>(offset);
    static_cast<void>(size);
    static_cast<void>(format);
    static_cast<void>(type);
    static_cast<void>(dataSize);
    static_cast<void>(data);
    #endif
}
#endif

}
<|endoftext|>


<commit_before>#include "acmacs-base/argv.hh"
#include "acmacs-base/guile.hh"
#include "acmacs-chart-2/chart-modify.hh"
#include "acmacs-chart-2/factory-import.hh"

// ----------------------------------------------------------------------

using namespace acmacs::argv;
struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    option<str_array> scripts{*this, 's', desc{"run scheme script (multiple switches allowed) before processing files"}};
    option<str_array> verbose{*this, 'v', "verbose", desc{"comma separated list (or multiple switches) of log enablers"}};

    argument<str> to_eval{*this, arg_name{"<guile-expression>"}, mandatory};
};

static void guile_defines();

int main(int argc, char* const argv[])
{
    using namespace std::string_view_literals;
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        acmacs::log::enable(opt.verbose);
        guile::init(guile_defines, *opt.scripts);
        scm_c_eval_string(opt.to_eval->data());
    }
    catch (std::exception& err) {
        AD_ERROR("{}", err);
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------

static SCM load_chart(SCM args);

void guile_defines()
{
    using namespace guile;
    using namespace std::string_view_literals;

    define("load-chart"sv, load_chart);
    // scm_c_define_gsubr("load-chart", 0, 0, 1, guile::subr(load_chart));

} // guile_defines

// ----------------------------------------------------------------------

SCM load_chart(SCM filename)
{
    auto chart = std::make_unique<acmacs::chart::ChartModify>(acmacs::chart::import_from_file(guile::from_scm<std::string>(filename)));
    fmt::print("loaded: {}\n", chart->make_name());
    return guile::VOID;

} // load_chart

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>guile-test<commit_after>#include "acmacs-base/argv.hh"
#include "acmacs-base/guile.hh"
#include "acmacs-chart-2/chart-modify.hh"
#include "acmacs-chart-2/factory-import.hh"

// ----------------------------------------------------------------------

using namespace acmacs::argv;
struct Options : public argv
{
    Options(int a_argc, const char* const a_argv[], on_error on_err = on_error::exit) : argv() { parse(a_argc, a_argv, on_err); }

    option<str_array> scripts{*this, 's', desc{"run scheme script (multiple switches allowed) before processing files"}};
    option<str_array> verbose{*this, 'v', "verbose", desc{"comma separated list (or multiple switches) of log enablers"}};

    argument<str> to_eval{*this, arg_name{"<guile-expression>"}, mandatory};
};

static void guile_defines();

int main(int argc, char* const argv[])
{
    using namespace std::string_view_literals;
    int exit_code = 0;
    try {
        Options opt(argc, argv);
        acmacs::log::enable(opt.verbose);
        guile::init(guile_defines, *opt.scripts);
        scm_c_eval_string(opt.to_eval->data());
    }
    catch (std::exception& err) {
        AD_ERROR("{}", err);
        exit_code = 2;
    }
    return exit_code;
}

// ----------------------------------------------------------------------

static SCM load_chart(SCM filename);
static SCM chart_name(SCM chart);
static SCM chart_type;

struct Sample
{
    Sample(std::string_view a_name) : name(a_name) { AD_DEBUG("Sample({})", name); }
    ~Sample() { AD_DEBUG("~Sample[{}]", name); }
    std::string name;

    static inline void finalize(SCM sample_obj) { delete static_cast<Sample*>(scm_foreign_object_ref(sample_obj, 0)); }
};

void guile_defines()
{
    using namespace guile;
    using namespace std::string_view_literals;

    // scm_c_eval_string("(use-modules (oop goops))");

    chart_type = scm_make_foreign_object_type(scm_from_utf8_symbol("<Chart>"), scm_list_1(scm_from_utf8_symbol("data")), Sample::finalize);
    define("load-chart"sv, load_chart);
    define("chart-name"sv, chart_name);
    // scm_c_define_gsubr("load-chart", 0, 0, 1, guile::subr(load_chart));

} // guile_defines

// ----------------------------------------------------------------------

SCM load_chart(SCM filename)
{
    // auto chart = new acmacs::chart::ChartModify(acmacs::chart::import_from_file(guile::from_scm<std::string>(filename)));
    // fmt::print("loaded: {}\n", chart->make_name());
    // return scm_make_foreign_object_1(chart_type, chart);

    auto chart = new Sample {guile::from_scm<std::string>(filename)};
    return scm_make_foreign_object_1(chart_type, chart);

} // load_chart

// ----------------------------------------------------------------------

SCM chart_name(SCM chart_obj)
{
    scm_assert_foreign_object_type(chart_type, chart_obj);
    auto* chart = static_cast<Sample*>(scm_foreign_object_ref(chart_obj, 0));
    return guile::to_scm(chart->name);

} // chart_name

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#pragma once

#include <cmath>
#include <limits>
#include <iostream>

#include "acmacs-base/float.hh"
#include "acmacs-base/to-string.hh"

// ----------------------------------------------------------------------

namespace acmacs::detail
{
    template <char Tag> class SizeScale
    {
     public:
        constexpr SizeScale() : mValue(0) {}
        constexpr explicit SizeScale(double aValue) : mValue(aValue) {}
        constexpr SizeScale(const SizeScale& a) = default;
        constexpr bool operator==(SizeScale<Tag> a) const { return float_equal(mValue, a.mValue); }
        constexpr bool operator!=(SizeScale<Tag> a) const { return !operator==(a); }
        constexpr bool operator<(SizeScale<Tag> a) const { return mValue < a.mValue; }
        constexpr SizeScale& operator = (double aValue) { mValue = aValue; return *this; }
        constexpr SizeScale& operator = (const SizeScale& a) = default;
        constexpr double value() const { return mValue; }
        constexpr SizeScale operator / (double a) const { return SizeScale{mValue / a}; }
        constexpr SizeScale operator * (double a) const { return SizeScale{mValue * a}; }
        constexpr SizeScale& operator *= (double a) { mValue *= a; return *this; }
        constexpr SizeScale operator - () const { return SizeScale{- mValue}; }
        constexpr SizeScale operator - (SizeScale<Tag> a) const { return SizeScale{mValue - a.mValue}; }
        constexpr SizeScale operator + (SizeScale<Tag> a) const { return SizeScale{mValue + a.mValue}; }
        constexpr SizeScale& operator += (SizeScale<Tag> a) { mValue += a.mValue; return *this; }
        constexpr bool empty() const { return std::isnan(mValue); }
        static constexpr SizeScale make_empty() { return SizeScale(std::numeric_limits<double>::quiet_NaN()); }

     private:
        double mValue;
    };
}

using Pixels = acmacs::detail::SizeScale<'P'>; // size in pixels, indepenent from the surface internal coordinate system
using Scaled = acmacs::detail::SizeScale<'S'>; // size in the surface internal coordinate system

// ----------------------------------------------------------------------

using Aspect = acmacs::detail::SizeScale<'A'>;
using Rotation = acmacs::detail::SizeScale<'R'>;

constexpr inline Rotation RotationDegrees(double aAngle)
{
    return Rotation{aAngle * M_PI / 180.0};
}

constexpr const Rotation NoRotation{0.0};
constexpr const Rotation RotationReassortant{0.5};
constexpr const Rotation Rotation90DegreesClockwise{RotationDegrees(90)};
constexpr const Rotation Rotation90DegreesAnticlockwise{RotationDegrees(-90)};
constexpr const Aspect AspectNormal{1.0};
constexpr const Aspect AspectEgg{0.75};

// ----------------------------------------------------------------------

inline std::ostream& operator<<(std::ostream& out, Pixels aPixels) { return out << "Pixels{" << aPixels.value() << '}'; }
inline std::ostream& operator<<(std::ostream& out, Scaled aScaled) { return out << "Scaled{" << aScaled.value() << '}'; }
inline std::ostream& operator<<(std::ostream& out, Aspect aAspect) { if (aAspect == AspectNormal) return out << "AspectNormal"; else return out << "Aspect{" << aAspect.value() << '}'; }
inline std::ostream& operator<<(std::ostream& out, Rotation aRotation) { if (aRotation == NoRotation) return out << "NoRotation"; else return out << "Rotation{" << aRotation.value() << '}'; }

namespace acmacs
{
    inline std::string to_string(Aspect aAspect) { return aAspect == AspectNormal ? std::string{"1.0"} : to_string(aAspect.value()); }
    inline std::string to_string(Rotation aRotation) { return aRotation == NoRotation ? std::string{"0.0"} : to_string(aRotation.value()); }
    inline std::string to_string(Pixels aPixels) { return to_string(aPixels.value()); }
    inline std::string to_string(Scaled aScaled) { return to_string(aScaled.value()); }

} // namespace acmacs

namespace acmacs::detail
{
    using ::operator<<;

} // namespace acmacs::detail

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>SizeScale improvement<commit_after>#pragma once

#include <cmath>
#include <limits>
#include <iostream>

#include "acmacs-base/float.hh"
#include "acmacs-base/to-string.hh"
#include "acmacs-base/fmt.hh"

// ----------------------------------------------------------------------

namespace acmacs::detail
{
    template <typename Tag> class SizeScale
    {
     public:
        constexpr explicit SizeScale() : mValue{0} {}
        constexpr explicit SizeScale(double aValue) : mValue{aValue} {}
        constexpr SizeScale(const SizeScale& a) = default;
        constexpr bool operator==(SizeScale<Tag> a) const { return float_equal(mValue, a.mValue); }
        constexpr bool operator!=(SizeScale<Tag> a) const { return !operator==(a); }
        constexpr bool operator<(SizeScale<Tag> a) const { return mValue < a.mValue; }
        constexpr SizeScale& operator = (double aValue) { mValue = aValue; return *this; }
        constexpr SizeScale& operator = (const SizeScale& a) = default;
        constexpr double value() const { return mValue; }
        constexpr SizeScale operator / (double a) const { return SizeScale{mValue / a}; }
        constexpr SizeScale operator * (double a) const { return SizeScale{mValue * a}; }
        constexpr SizeScale& operator *= (double a) { mValue *= a; return *this; }
        constexpr SizeScale operator - () const { return SizeScale{- mValue}; }
        constexpr SizeScale operator - (SizeScale<Tag> a) const { return SizeScale{mValue - a.mValue}; }
        constexpr SizeScale operator + (SizeScale<Tag> a) const { return SizeScale{mValue + a.mValue}; }
        constexpr SizeScale& operator += (SizeScale<Tag> a) { mValue += a.mValue; return *this; }
        constexpr bool empty() const { return std::isnan(mValue); }
        static constexpr SizeScale make_empty() { return SizeScale(std::numeric_limits<double>::quiet_NaN()); }

     private:
        double mValue;
    };
}

using Pixels = acmacs::detail::SizeScale<struct Pixels_tag>; // size in pixels, indepenent from the surface internal coordinate system
using Scaled = acmacs::detail::SizeScale<struct Scaled_tag>; // size in the surface internal coordinate system

// ----------------------------------------------------------------------

using Aspect = acmacs::detail::SizeScale<struct Aspect_tag>;
using Rotation = acmacs::detail::SizeScale<struct Rotation_tag>;

constexpr inline Rotation RotationDegrees(double aAngle)
{
    return Rotation{aAngle * M_PI / 180.0};
}

constexpr const Rotation NoRotation{0.0};
constexpr const Rotation RotationReassortant{0.5};
constexpr const Rotation Rotation90DegreesClockwise{RotationDegrees(90)};
constexpr const Rotation Rotation90DegreesAnticlockwise{RotationDegrees(-90)};
constexpr const Aspect AspectNormal{1.0};
constexpr const Aspect AspectEgg{0.75};

// ----------------------------------------------------------------------

inline std::ostream& operator<<(std::ostream& out, Pixels aPixels) { return out << "Pixels{" << aPixels.value() << '}'; }
inline std::ostream& operator<<(std::ostream& out, Scaled aScaled) { return out << "Scaled{" << aScaled.value() << '}'; }
inline std::ostream& operator<<(std::ostream& out, Aspect aAspect) { if (aAspect == AspectNormal) return out << "AspectNormal"; else return out << "Aspect{" << aAspect.value() << '}'; }
inline std::ostream& operator<<(std::ostream& out, Rotation aRotation) { if (aRotation == NoRotation) return out << "NoRotation"; else return out << "Rotation{" << aRotation.value() << '}'; }

namespace acmacs
{
    inline std::string to_string(Aspect aAspect) { return aAspect == AspectNormal ? std::string{"1.0"} : to_string(aAspect.value()); }
    inline std::string to_string(Rotation aRotation) { return aRotation == NoRotation ? std::string{"0.0"} : to_string(aRotation.value()); }
    inline std::string to_string(Pixels aPixels) { return to_string(aPixels.value()); }
    inline std::string to_string(Scaled aScaled) { return to_string(aScaled.value()); }

} // namespace acmacs

namespace acmacs::detail
{
    using ::operator<<;

} // namespace acmacs::detail

// ----------------------------------------------------------------------

template <> struct fmt::formatter<Pixels>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const Pixels& pixels, FormatContext& ctx) { return format_to(ctx.out(), "{}px", pixels.value()); }
};

template <> struct fmt::formatter<Scaled>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const Scaled& scaled, FormatContext& ctx) { return format_to(ctx.out(), "{}scaled", scaled.value()); }
};

template <> struct fmt::formatter<Rotation>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const Rotation& rotation, FormatContext& ctx) { return format_to(ctx.out(), "{}", rotation.value()); }
};

template <> struct fmt::formatter<Aspect>
{
    template <typename ParseContext> constexpr auto parse(ParseContext &ctx) { return ctx.begin(); }
    template <typename FormatContext> auto format(const Aspect& aspect, FormatContext& ctx) { return format_to(ctx.out(), "{}", aspect.value()); }
};

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdlib>
#include "min_max_heap.h"
#include "min_max_heap_test.h"

using namespace std;

void min_max_heap_test()
{
    const int num_experiments = 500;
    min_max_heap my_min_max_heap(num_experiments);
    int data[num_experiments];
    for (int i = 0; i < num_experiments; i++)
    {
        data[i] = -1;
    }
    for (int i = 0; i < num_experiments; i++)
    {
        int operation = rand() % 3;
        if (my_min_max_heap.get_size() == 0)
        {
            // the only valid operation is insert a random value if the size is 0
            operation = 0;
        }

        if (operation == 0)
        {
            int value = rand() % 50;
            cout << i << ":\t Insert " << value << endl;
            // Naive implementation
            for (int i = 0; i < num_experiments; i++)
            {
                if (data[i] == -1)
                {
                    data[i] = value;
                    break;
                }
            }

            if (!my_min_max_heap.try_insert(value))
            {
                cout << "Fail" << endl;
            }
        }
        else if (operation == 1)
        {
            cout << i << ":\t Delete min" << endl;
            int min_value = INT_MAX;
            int min_index = -1;
            // Naive implementation
            for (int j = 0; j < num_experiments; j++)
            {
                if (data[j] != -1)
                {
                    if (data[j] < min_value)
                    {
                        min_value = data[j];
                        min_index = j;
                    }
                }
            }
            data[min_index] = -1;
            double test_min_value;
            if (!my_min_max_heap.try_delete_min(&test_min_value))
            {
                cout << "Fail" << endl;
            }
            if (test_min_value != min_value)
            {
                cout << "Fail" << endl;
            }
            if (!my_min_max_heap.verify_consistency())
            {
                cout << "Fail" << endl;
            }
        }
        else if (operation == 2)
        {
            cout << i << ":\t Delete max" << endl;
            int max_value = INT_MIN;
            int max_index = -1;
            // Naive implementation
            for (int j = 0; j < num_experiments; j++)
            {
                if (data[j] != -1)
                {
                    if (data[j] > max_value)
                    {
                        max_value = data[j];
                        max_index = j;
                    }
                }
            }
            data[max_index] = -1;
            double test_max_value;
            if (!my_min_max_heap.try_delete_max(&test_max_value))
            {
                cout << "Fail" << endl;
            }
            if (test_max_value != max_value)
            {
                cout << "Fail" << endl;
            }
            if (!my_min_max_heap.verify_consistency())
            {
                cout << "Fail" << endl;
            }
        }
    }
}
<commit_msg>Fix Linux build<commit_after>#include <iostream>
#include <cstdlib>
#include <limits.h>
#include "min_max_heap.h"
#include "min_max_heap_test.h"

using namespace std;

void min_max_heap_test()
{
    const int num_experiments = 500;
    min_max_heap my_min_max_heap(num_experiments);
    int data[num_experiments];
    for (int i = 0; i < num_experiments; i++)
    {
        data[i] = -1;
    }
    for (int i = 0; i < num_experiments; i++)
    {
        int operation = rand() % 3;
        if (my_min_max_heap.get_size() == 0)
        {
            // the only valid operation is insert a random value if the size is 0
            operation = 0;
        }

        if (operation == 0)
        {
            int value = rand() % 50;
            cout << i << ":\t Insert " << value << endl;
            // Naive implementation
            for (int i = 0; i < num_experiments; i++)
            {
                if (data[i] == -1)
                {
                    data[i] = value;
                    break;
                }
            }

            if (!my_min_max_heap.try_insert(value))
            {
                cout << "Fail" << endl;
            }
        }
        else if (operation == 1)
        {
            cout << i << ":\t Delete min" << endl;
            int min_value = INT_MAX;
            int min_index = -1;
            // Naive implementation
            for (int j = 0; j < num_experiments; j++)
            {
                if (data[j] != -1)
                {
                    if (data[j] < min_value)
                    {
                        min_value = data[j];
                        min_index = j;
                    }
                }
            }
            data[min_index] = -1;
            double test_min_value;
            if (!my_min_max_heap.try_delete_min(&test_min_value))
            {
                cout << "Fail" << endl;
            }
            if (test_min_value != min_value)
            {
                cout << "Fail" << endl;
            }
            if (!my_min_max_heap.verify_consistency())
            {
                cout << "Fail" << endl;
            }
        }
        else if (operation == 2)
        {
            cout << i << ":\t Delete max" << endl;
            int max_value = INT_MIN;
            int max_index = -1;
            // Naive implementation
            for (int j = 0; j < num_experiments; j++)
            {
                if (data[j] != -1)
                {
                    if (data[j] > max_value)
                    {
                        max_value = data[j];
                        max_index = j;
                    }
                }
            }
            data[max_index] = -1;
            double test_max_value;
            if (!my_min_max_heap.try_delete_max(&test_max_value))
            {
                cout << "Fail" << endl;
            }
            if (test_max_value != max_value)
            {
                cout << "Fail" << endl;
            }
            if (!my_min_max_heap.verify_consistency())
            {
                cout << "Fail" << endl;
            }
        }
    }
}
<|endoftext|>


<commit_before>#include<iostream>
#include<iomanip>

using namespace std;

struct Trabajadores{
	string nombre;
	float salario;
}T[20];

int main(){

}
<commit_msg>Agregando<commit_after>#include<iostream>
#include<iomanip>

using namespace std;

/*
Variables
Son 20 Empleados
Leer a Cada uno
Nombre, Horas de Trabajo, Base de Pago, Edad

Otras Variables
Impuestos, Saldo Neto
*/

struct Trabajadores{
	string nombre;
	float salario;
}T[20];

int main(){

}
<|endoftext|>


<commit_before>//---------------------------------------------------------------------------//
/*
  Copyright (c) 2012, Stuart R. Slattery
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

  *: Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

  *: Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

  *: Neither the name of the University of Wisconsin - Madison nor the
  names of its contributors may be used to endorse or promote products
  derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//---------------------------------------------------------------------------//
/*!
 * \file Chimera_HistoryBank.hpp
 * \author Stuart R. Slattery
 * \brief HistoryBank definition.
 */
//---------------------------------------------------------------------------//

#ifndef Chimera_HISTORYBANK_HPP
#define Chimera_HISTORYBANK_HPP

#include "Chimera_Assertion.hpp"

#include <Teuchos_Array.hpp>

namespace Chimera
{
//---------------------------------------------------------------------------//
/*!
 * \class HistoryBank
 * \brief History bank.
 *
 * This class is a stack using a Teuchos::Array as the underlying data
 * structure so that we may use it for communication operations.
 */
//---------------------------------------------------------------------------//
template<class HT>
class HistoryBank
{
  public:

    //@{
    //! Typedefs.
    typedef HT                                             history_type;
    typedef typename Teuchos::Array<HT>::size_type         size_type;
    //@}

    //! Default constructor.
    HistoryBank()
	: d_histories( 0 )
    { /* ... */ }

    //! Stack constructor.
    HistoryBank( const Teuchos::Array<HT>& histories )
	: d_histories( histories )
    { /* ... */ }

    //! Destructor.
    ~HistoryBank()
    { /* ... */ }

    //! Set the history stack.
    void setStack( const Teuchos::Array<HT>& histories )
    { d_histories = histories; }

    //! Return if the bank is empty.
    bool empty () const
    { return d_histories.empty(); }

    //! Return the number of histories left in the bank.
    size_type size() const
    { return d_histories.size(); }

    //! Access the top history in the stack.
    inline const HT& top() const;

    //! Push history onto the stack.
    void push( const HT& history )
    { d_histories.push_back(history); }

    //! Pop a history off of the stack.
    inline HT pop();

  private:

    // History stack.
    Teuchos::Array<HT> d_histories;
};

//---------------------------------------------------------------------------//
// Inline functions.
//---------------------------------------------------------------------------//
template<class HT>
const HT& HistoryBank<HT>::top() const
{
    testPrecondition( !empty() );
    return d_histories.back();
}

//---------------------------------------------------------------------------//
template<class HT>
HT HistoryBank<HT>::pop()
{
    testPrecondition( !empty() );
    HT history = d_histories.back();
    d_histories.pop_back();
    return history;
}

//---------------------------------------------------------------------------//

} // end namespace Chimera

#endif // end Chimera_HISTORYBANK_HPP

//---------------------------------------------------------------------------//
// end Chimera_HistoryBank.hpp
//---------------------------------------------------------------------------//

<commit_msg>added non-const reference access to top of bank stack<commit_after>//---------------------------------------------------------------------------//
/*
  Copyright (c) 2012, Stuart R. Slattery
  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:

  *: Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

  *: Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

  *: Neither the name of the University of Wisconsin - Madison nor the
  names of its contributors may be used to endorse or promote products
  derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//---------------------------------------------------------------------------//
/*!
 * \file Chimera_HistoryBank.hpp
 * \author Stuart R. Slattery
 * \brief HistoryBank definition.
 */
//---------------------------------------------------------------------------//

#ifndef Chimera_HISTORYBANK_HPP
#define Chimera_HISTORYBANK_HPP

#include "Chimera_Assertion.hpp"

#include <Teuchos_Array.hpp>

namespace Chimera
{
//---------------------------------------------------------------------------//
/*!
 * \class HistoryBank
 * \brief History bank.
 *
 * This class is a stack using a Teuchos::Array as the underlying data
 * structure so that we may use it for communication operations.
 */
//---------------------------------------------------------------------------//
template<class HT>
class HistoryBank
{
  public:

    //@{
    //! Typedefs.
    typedef HT                                             history_type;
    typedef typename Teuchos::Array<HT>::size_type         size_type;
    //@}

    //! Default constructor.
    HistoryBank()
	: d_histories( 0 )
    { /* ... */ }

    //! Stack constructor.
    HistoryBank( const Teuchos::Array<HT>& histories )
	: d_histories( histories )
    { /* ... */ }

    //! Destructor.
    ~HistoryBank()
    { /* ... */ }

    //! Set the history stack.
    void setStack( const Teuchos::Array<HT>& histories )
    { d_histories = histories; }

    //! Return if the bank is empty.
    bool empty () const
    { return d_histories.empty(); }

    //! Return the number of histories left in the bank.
    size_type size() const
    { return d_histories.size(); }

    //! Access the top history in the stack.
    inline const HT& top() const;
    inline HT& top();

    //! Push history onto the stack.
    void push( const HT& history )
    { d_histories.push_back(history); }

    //! Pop a history off of the stack.
    inline HT pop();

  private:

    // History stack.
    Teuchos::Array<HT> d_histories;
};

//---------------------------------------------------------------------------//
// Inline functions.
//---------------------------------------------------------------------------//
template<class HT>
const HT& HistoryBank<HT>::top() const
{
    testPrecondition( !empty() );
    return d_histories.back();
}

template<class HT>
HT& HistoryBank<HT>::top()
{
    testPrecondition( !empty() );
    return d_histories.back();
}

//---------------------------------------------------------------------------//
template<class HT>
HT HistoryBank<HT>::pop()
{
    testPrecondition( !empty() );
    HT history = d_histories.back();
    d_histories.pop_back();
    return history;
}

//---------------------------------------------------------------------------//

} // end namespace Chimera

#endif // end Chimera_HISTORYBANK_HPP

//---------------------------------------------------------------------------//
// end Chimera_HistoryBank.hpp
//---------------------------------------------------------------------------//

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.1 (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.mozilla.org/NPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the NPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the NPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "npapi.h"
#include "npupp.h"

//\\// DEFINE
#define NP_EXPORT

//\\// GLOBAL DATA
NPNetscapeFuncs* g_pNavigatorFuncs = 0;

extern "C"
{
#ifdef OJI
JRIGlobalRef Private_GetJavaClass(void);

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
// Private_GetJavaClass (global function)
//
//  Given a Java class reference (thru NPP_GetJavaClass) inform JRT
//  of this class existence
//
JRIGlobalRef
Private_GetJavaClass(void)
{
    jref clazz = NPP_GetJavaClass();
    if (clazz) {
        JRIEnv* env = NPN_GetJavaEnv();
        return JRI_NewGlobalRef(env, clazz);
    }
    return NULL;
}
#endif /* OJI */

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
//                      PLUGIN DLL entry points
//
// These are the Windows specific DLL entry points. They must be exoprted
//

// we need these to be global since we have to fill one of its field
// with a data (class) which requires knowlwdge of the navigator
// jump-table. This jump table is known at Initialize time (NP_Initialize)
// which is called after NP_GetEntryPoint
static NPPluginFuncs* g_pluginFuncs;

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
// NP_GetEntryPoints
//
//  fills in the func table used by Navigator to call entry points in
//  plugin DLL.  Note that these entry points ensure that DS is loaded
//  by using the NP_LOADDS macro, when compiling for Win16
//
NPError WINAPI NP_EXPORT
NP_GetEntryPoints(NPPluginFuncs* pFuncs)
{
    // trap a NULL ptr
    if(pFuncs == NULL)
        return NPERR_INVALID_FUNCTABLE_ERROR;

    // if the plugin's function table is smaller than the plugin expects,
    // then they are incompatible, and should return an error

    pFuncs->version       = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
    pFuncs->newp          = NPP_New;
    pFuncs->destroy       = NPP_Destroy;
    pFuncs->setwindow     = NPP_SetWindow;
    pFuncs->newstream     = NPP_NewStream;
    pFuncs->destroystream = NPP_DestroyStream;
    pFuncs->asfile        = NPP_StreamAsFile;
    pFuncs->writeready    = NPP_WriteReady;
    pFuncs->write         = NPP_Write;
    pFuncs->print         = NPP_Print;
    pFuncs->event         = 0;       /// reserved

    g_pluginFuncs         = pFuncs;

    return NPERR_NO_ERROR;
}

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
// NP_Initialize
//
//  called immediately after the plugin DLL is loaded
//
NPError WINAPI NP_EXPORT
NP_Initialize(NPNetscapeFuncs* pFuncs)
{
    // trap a NULL ptr
    if(pFuncs == NULL)
        return NPERR_INVALID_FUNCTABLE_ERROR;

    g_pNavigatorFuncs = pFuncs; // save it for future reference

    // if the plugin's major ver level is lower than the Navigator's,
    // then they are incompatible, and should return an error
    if(HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
        return NPERR_INCOMPATIBLE_VERSION_ERROR;

    // We have to defer these assignments until g_pNavigatorFuncs is set
    int navMinorVers = g_pNavigatorFuncs->version & 0xFF;

    if( navMinorVers >= NPVERS_HAS_NOTIFICATION ) {
        g_pluginFuncs->urlnotify = NPP_URLNotify;
    }

#ifdef OJI
    if( navMinorVers >= NPVERS_HAS_LIVECONNECT ) {
        g_pluginFuncs->javaClass = Private_GetJavaClass();
    }
#endif

    return NPERR_NO_ERROR;
}

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
// NP_Shutdown
//
//  called immediately before the plugin DLL is unloaded.
//  This functio shuold check for some ref count on the dll to see if it is
//  unloadable or it needs to stay in memory.
//
void WINAPI NP_EXPORT
NP_Shutdown()
{
    g_pNavigatorFuncs = NULL;
}

char * NP_GetMIMEDescription()
{
    return NPP_GetMIMEDescription();
}

//                      END - PLUGIN DLL entry points
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.

/*    NAVIGATOR Entry points    */

/* These entry points expect to be called from within the plugin.  The
   noteworthy assumption is that DS has already been set to point to the
   plugin's DLL data segment.  Don't call these functions from outside
   the plugin without ensuring DS is set to the DLLs data segment first,
   typically using the NP_LOADDS macro
*/

/* returns the major/minor version numbers of the Plugin API for the plugin
   and the Navigator
*/
void NPN_Version(int* plugin_major, int* plugin_minor, int* netscape_major, int* netscape_minor)
{
    *plugin_major   = NP_VERSION_MAJOR;
    *plugin_minor   = NP_VERSION_MINOR;
    *netscape_major = HIBYTE(g_pNavigatorFuncs->version);
    *netscape_minor = LOBYTE(g_pNavigatorFuncs->version);
}

NPError NPN_GetValue(NPP instance, NPNVariable variable, void *result)
{
    return g_pNavigatorFuncs->getvalue(instance, variable, result);
}

/* causes the specified URL to be fetched and streamed in
*/
NPError NPN_GetURLNotify(NPP instance, const char *url, const char *target, void* notifyData)

{
    int navMinorVers = g_pNavigatorFuncs->version & 0xFF;
    NPError err;
    if( navMinorVers >= NPVERS_HAS_NOTIFICATION ) {
        err = g_pNavigatorFuncs->geturlnotify(instance, url, target, notifyData);
    }
    else {
        err = NPERR_INCOMPATIBLE_VERSION_ERROR;
    }
    return err;
}

NPError NPN_GetURL(NPP instance, const char *url, const char *target)
{
    return g_pNavigatorFuncs->geturl(instance, url, target);
}

NPError NPN_PostURLNotify(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file, void* notifyData)
{
    int navMinorVers = g_pNavigatorFuncs->version & 0xFF;
    NPError err;
    if( navMinorVers >= NPVERS_HAS_NOTIFICATION ) {
        err = g_pNavigatorFuncs->posturlnotify(instance, url, window, len, buf, file, notifyData);
    }
    else {
        err = NPERR_INCOMPATIBLE_VERSION_ERROR;
    }
    return err;
}

NPError NPN_PostURL(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file)
{
    return g_pNavigatorFuncs->posturl(instance, url, window, len, buf, file);
}

/* Requests that a number of bytes be provided on a stream.  Typically
   this would be used if a stream was in "pull" mode.  An optional
   position can be provided for streams which are seekable.
*/
NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
{
    return g_pNavigatorFuncs->requestread(stream, rangeList);
}

/* Creates a new stream of data from the plug-in to be interpreted
   by Netscape in the current window.
*/
NPError NPN_NewStream(NPP instance, NPMIMEType type,
                                const char* target, NPStream** stream)
{
    int navMinorVersion = g_pNavigatorFuncs->version & 0xFF;
    NPError err;

    if( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT ) {
        err = g_pNavigatorFuncs->newstream(instance, type, target, stream);
    }
    else {
        err = NPERR_INCOMPATIBLE_VERSION_ERROR;
    }
    return err;
}

/* Provides len bytes of data.
*/
int32_t NPN_Write(NPP instance, NPStream *stream,
                int32_t len, void *buffer)
{
    int navMinorVersion = g_pNavigatorFuncs->version & 0xFF;
    int32_t result;

    if( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT ) {
        result = g_pNavigatorFuncs->write(instance, stream, len, buffer);
    }
    else {
        result = -1;
    }
    return result;
}

/* Closes a stream object.
reason indicates why the stream was closed.
*/
NPError NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason)
{
    int navMinorVersion = g_pNavigatorFuncs->version & 0xFF;
    NPError err;

    if( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT ) {
        err = g_pNavigatorFuncs->destroystream(instance, stream, reason);
    }
    else {
        err = NPERR_INCOMPATIBLE_VERSION_ERROR;
    }
    return err;
}

/* Provides a text status message in the Netscape client user interface
*/
void NPN_Status(NPP instance, const char *message)
{
    g_pNavigatorFuncs->status(instance, message);
}

/* returns the user agent string of Navigator, which contains version info
*/
const char* NPN_UserAgent(NPP instance)
{
    return g_pNavigatorFuncs->uagent(instance);
}

/* allocates memory from the Navigator's memory space.  Necessary so that
   saved instance data may be freed by Navigator when exiting.
*/

void* NPN_MemAlloc(uint32_t size)
{
    return g_pNavigatorFuncs->memalloc(size);
}

/* reciprocal of MemAlloc() above
*/
void NPN_MemFree(void* ptr)
{
    g_pNavigatorFuncs->memfree(ptr);
}

#ifdef OJI
/* private function to Netscape.  do not use!
*/
void NPN_ReloadPlugins(NPBool reloadPages)
{
    g_pNavigatorFuncs->reloadplugins(reloadPages);
}

JRIEnv* NPN_GetJavaEnv(void)
{
    return g_pNavigatorFuncs->getJavaEnv();
}

jref NPN_GetJavaPeer(NPP instance)
{
    return g_pNavigatorFuncs->getJavaPeer(instance);
}
#endif
} //end of extern "C"

<commit_msg>WaE: add horror cast to calm Windows tinderbox<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.1 (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.mozilla.org/NPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the NPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the NPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

#include "npapi.h"
#include "npupp.h"

//\\// DEFINE
#define NP_EXPORT

//\\// GLOBAL DATA
NPNetscapeFuncs* g_pNavigatorFuncs = 0;

extern "C"
{
#ifdef OJI
JRIGlobalRef Private_GetJavaClass(void);

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
// Private_GetJavaClass (global function)
//
//  Given a Java class reference (thru NPP_GetJavaClass) inform JRT
//  of this class existence
//
JRIGlobalRef
Private_GetJavaClass(void)
{
    jref clazz = NPP_GetJavaClass();
    if (clazz) {
        JRIEnv* env = NPN_GetJavaEnv();
        return JRI_NewGlobalRef(env, clazz);
    }
    return NULL;
}
#endif /* OJI */

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
//                      PLUGIN DLL entry points
//
// These are the Windows specific DLL entry points. They must be exoprted
//

// we need these to be global since we have to fill one of its field
// with a data (class) which requires knowlwdge of the navigator
// jump-table. This jump table is known at Initialize time (NP_Initialize)
// which is called after NP_GetEntryPoint
static NPPluginFuncs* g_pluginFuncs;

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
// NP_GetEntryPoints
//
//  fills in the func table used by Navigator to call entry points in
//  plugin DLL.  Note that these entry points ensure that DS is loaded
//  by using the NP_LOADDS macro, when compiling for Win16
//
NPError WINAPI NP_EXPORT
NP_GetEntryPoints(NPPluginFuncs* pFuncs)
{
    // trap a NULL ptr
    if(pFuncs == NULL)
        return NPERR_INVALID_FUNCTABLE_ERROR;

    // if the plugin's function table is smaller than the plugin expects,
    // then they are incompatible, and should return an error

    pFuncs->version       = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
    pFuncs->newp          = NPP_New;
    pFuncs->destroy       = NPP_Destroy;
    pFuncs->setwindow     = NPP_SetWindow;
    pFuncs->newstream     = NPP_NewStream;
    pFuncs->destroystream = NPP_DestroyStream;
    pFuncs->asfile        = NPP_StreamAsFile;
    pFuncs->writeready    = NPP_WriteReady;
    pFuncs->write         = NPP_Write;
    pFuncs->print         = NPP_Print;
    pFuncs->event         = 0;       /// reserved

    g_pluginFuncs         = pFuncs;

    return NPERR_NO_ERROR;
}

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
// NP_Initialize
//
//  called immediately after the plugin DLL is loaded
//
NPError WINAPI NP_EXPORT
NP_Initialize(NPNetscapeFuncs* pFuncs)
{
    // trap a NULL ptr
    if(pFuncs == NULL)
        return NPERR_INVALID_FUNCTABLE_ERROR;

    g_pNavigatorFuncs = pFuncs; // save it for future reference

    // if the plugin's major ver level is lower than the Navigator's,
    // then they are incompatible, and should return an error
    if(HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
        return NPERR_INCOMPATIBLE_VERSION_ERROR;

    // We have to defer these assignments until g_pNavigatorFuncs is set
    int navMinorVers = g_pNavigatorFuncs->version & 0xFF;

    if( navMinorVers >= NPVERS_HAS_NOTIFICATION ) {
        g_pluginFuncs->urlnotify = NPP_URLNotify;
    }

#ifdef OJI
    if( navMinorVers >= NPVERS_HAS_LIVECONNECT ) {
        g_pluginFuncs->javaClass = Private_GetJavaClass();
    }
#endif

    return NPERR_NO_ERROR;
}

//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
// NP_Shutdown
//
//  called immediately before the plugin DLL is unloaded.
//  This functio shuold check for some ref count on the dll to see if it is
//  unloadable or it needs to stay in memory.
//
void WINAPI NP_EXPORT
NP_Shutdown()
{
    g_pNavigatorFuncs = NULL;
}

char * NP_GetMIMEDescription()
{
  return (char *)NPP_GetMIMEDescription();
}

//                      END - PLUGIN DLL entry points
////\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//.
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\.

/*    NAVIGATOR Entry points    */

/* These entry points expect to be called from within the plugin.  The
   noteworthy assumption is that DS has already been set to point to the
   plugin's DLL data segment.  Don't call these functions from outside
   the plugin without ensuring DS is set to the DLLs data segment first,
   typically using the NP_LOADDS macro
*/

/* returns the major/minor version numbers of the Plugin API for the plugin
   and the Navigator
*/
void NPN_Version(int* plugin_major, int* plugin_minor, int* netscape_major, int* netscape_minor)
{
    *plugin_major   = NP_VERSION_MAJOR;
    *plugin_minor   = NP_VERSION_MINOR;
    *netscape_major = HIBYTE(g_pNavigatorFuncs->version);
    *netscape_minor = LOBYTE(g_pNavigatorFuncs->version);
}

NPError NPN_GetValue(NPP instance, NPNVariable variable, void *result)
{
    return g_pNavigatorFuncs->getvalue(instance, variable, result);
}

/* causes the specified URL to be fetched and streamed in
*/
NPError NPN_GetURLNotify(NPP instance, const char *url, const char *target, void* notifyData)

{
    int navMinorVers = g_pNavigatorFuncs->version & 0xFF;
    NPError err;
    if( navMinorVers >= NPVERS_HAS_NOTIFICATION ) {
        err = g_pNavigatorFuncs->geturlnotify(instance, url, target, notifyData);
    }
    else {
        err = NPERR_INCOMPATIBLE_VERSION_ERROR;
    }
    return err;
}

NPError NPN_GetURL(NPP instance, const char *url, const char *target)
{
    return g_pNavigatorFuncs->geturl(instance, url, target);
}

NPError NPN_PostURLNotify(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file, void* notifyData)
{
    int navMinorVers = g_pNavigatorFuncs->version & 0xFF;
    NPError err;
    if( navMinorVers >= NPVERS_HAS_NOTIFICATION ) {
        err = g_pNavigatorFuncs->posturlnotify(instance, url, window, len, buf, file, notifyData);
    }
    else {
        err = NPERR_INCOMPATIBLE_VERSION_ERROR;
    }
    return err;
}

NPError NPN_PostURL(NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file)
{
    return g_pNavigatorFuncs->posturl(instance, url, window, len, buf, file);
}

/* Requests that a number of bytes be provided on a stream.  Typically
   this would be used if a stream was in "pull" mode.  An optional
   position can be provided for streams which are seekable.
*/
NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
{
    return g_pNavigatorFuncs->requestread(stream, rangeList);
}

/* Creates a new stream of data from the plug-in to be interpreted
   by Netscape in the current window.
*/
NPError NPN_NewStream(NPP instance, NPMIMEType type,
                                const char* target, NPStream** stream)
{
    int navMinorVersion = g_pNavigatorFuncs->version & 0xFF;
    NPError err;

    if( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT ) {
        err = g_pNavigatorFuncs->newstream(instance, type, target, stream);
    }
    else {
        err = NPERR_INCOMPATIBLE_VERSION_ERROR;
    }
    return err;
}

/* Provides len bytes of data.
*/
int32_t NPN_Write(NPP instance, NPStream *stream,
                int32_t len, void *buffer)
{
    int navMinorVersion = g_pNavigatorFuncs->version & 0xFF;
    int32_t result;

    if( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT ) {
        result = g_pNavigatorFuncs->write(instance, stream, len, buffer);
    }
    else {
        result = -1;
    }
    return result;
}

/* Closes a stream object.
reason indicates why the stream was closed.
*/
NPError NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason)
{
    int navMinorVersion = g_pNavigatorFuncs->version & 0xFF;
    NPError err;

    if( navMinorVersion >= NPVERS_HAS_STREAMOUTPUT ) {
        err = g_pNavigatorFuncs->destroystream(instance, stream, reason);
    }
    else {
        err = NPERR_INCOMPATIBLE_VERSION_ERROR;
    }
    return err;
}

/* Provides a text status message in the Netscape client user interface
*/
void NPN_Status(NPP instance, const char *message)
{
    g_pNavigatorFuncs->status(instance, message);
}

/* returns the user agent string of Navigator, which contains version info
*/
const char* NPN_UserAgent(NPP instance)
{
    return g_pNavigatorFuncs->uagent(instance);
}

/* allocates memory from the Navigator's memory space.  Necessary so that
   saved instance data may be freed by Navigator when exiting.
*/

void* NPN_MemAlloc(uint32_t size)
{
    return g_pNavigatorFuncs->memalloc(size);
}

/* reciprocal of MemAlloc() above
*/
void NPN_MemFree(void* ptr)
{
    g_pNavigatorFuncs->memfree(ptr);
}

#ifdef OJI
/* private function to Netscape.  do not use!
*/
void NPN_ReloadPlugins(NPBool reloadPages)
{
    g_pNavigatorFuncs->reloadplugins(reloadPages);
}

JRIEnv* NPN_GetJavaEnv(void)
{
    return g_pNavigatorFuncs->getJavaEnv();
}

jref NPN_GetJavaPeer(NPP instance)
{
    return g_pNavigatorFuncs->getJavaPeer(instance);
}
#endif
} //end of extern "C"

<|endoftext|>