<commit_before>#include "src/fillers.h"
#include "src/utils.h"

/* ***** */
void gfx_flatFill(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double invDy, dxLeft, dxRight, xLeft, xRight;
    double y, yDir = 1;
    // variables used if depth test is enabled
    float startInvZ, endInvZ, invZ0, invZ1, invZ2, invY02;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    xLeft   = v0->position.x;
    xRight  = xLeft;

    // skip the unnecessary divisions if there's no depth testing
    if(buffer->drawOpts.depthFunc != DF_ALWAYS)
    {
        invZ0  = 1.f / v0->position.z;
        invZ1  = 1.f / v1->position.z;
        invZ2  = 1.f / v2->position.z;
        invY02 = 1.f / (v0->position.y - v2->position.y);
    }

    for(y = v0->position.y; ; y += yDir)
    {
        if(type == FLAT_TOP && y < v2->position.y)
            break;
        else if(type == FLAT_BOTTOM && y > v2->position.y)
        {
            // to avoid pixel wide gaps, render extra line at the junction between two final points
            if(buffer->drawOpts.depthFunc != DF_ALWAYS)
                gfx_drawLine(xLeft-dxLeft, y, 1.f/startInvZ, xRight-dxRight, y, 1.f/endInvZ, t->color, buffer);
            else
                gfx_drawLine(xLeft-dxLeft, y, 0.f, xRight-dxRight, y, 0.f, t->color, buffer);
            break;
        }

        // interpolate 1/z only if depth testing is enabled
        if(buffer->drawOpts.depthFunc != DF_ALWAYS)
        {
            float r1  = (v0->position.y - y) * invY02;
            startInvZ = LERP(invZ0, invZ2, r1);
            endInvZ   = LERP(invZ0, invZ1, r1);
            gfx_drawLine(xLeft, y, 1.f/startInvZ, xRight, y, 1.f/endInvZ, t->color, buffer);
        }
        else
            gfx_drawLine(xLeft, y, 0.f, xRight, y, 0.f, t->color, buffer);

        xLeft  += dxLeft;
        xRight += dxRight;
    }
}

/* ***** */
void gfx_perspectiveTextureMap(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double x, y, invDy, dxLeft, dxRight, yDir = 1;
    int   useColorKey = buffer->drawOpts.colorKey != -1 ? 1 : 0;
    int   texW = t->texture->width - 1;
    int   texH = t->texture->height - 1;
    int   texArea = texW * texH;
    float startX  = v0->position.x;
    float endX    = startX;
    float invZ0, invZ1, invZ2, invY02 = 1.f;
    int   finished = 0;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;

    invZ0  = 1.f / v0->position.z;
    invZ1  = 1.f / v1->position.z;
    invZ2  = 1.f / v2->position.z;
    invY02 = 1.f / (v0->position.y - v2->position.y);

    for(y = v0->position.y; ; y += yDir)
    {
        float startInvZ, endInvZ, r1, invLineLength = 0.f;
        float startU = texW, startV = texH, endU = texW, endV = texH;

        if(type == FLAT_BOTTOM && y > v2->position.y)
        {
            // in final iteration draw extra scanline to avoid pixel wide gaps
            startX -= dxLeft;
            endX   -= dxRight;
            y = v2->position.y;
            finished = 1;
        }
        else if ( type == FLAT_TOP && y < v2->position.y)
            break;

        r1 = (v0->position.y - y) * invY02;
        startInvZ = LERP(invZ0, invZ2, r1);
        endInvZ   = LERP(invZ0, invZ1, r1);

        startU *= LERP(v0->uv.u * invZ0, v2->uv.u * invZ2, r1);
        startV *= LERP(v0->uv.v * invZ0, v2->uv.v * invZ2, r1);
        endU   *= LERP(v0->uv.u * invZ0, v1->uv.u * invZ1, r1);
        endV   *= LERP(v0->uv.v * invZ0, v1->uv.v * invZ1, r1);

        if(startX != endX)
            invLineLength = 1.f / (endX - startX);

        for(x = startX; x <= endX; ++x)
        {
            // interpolate 1/z for each pixel in the scanline
            float r = (x - startX) * invLineLength;
            float lerpInvZ = LERP(startInvZ, endInvZ, r);
            float z = 1.f/lerpInvZ;
            float u = z * LERP(startU, endU, r);
            float v = z * LERP(startV, endV, r);

            // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
            unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

            if(!useColorKey || (useColorKey && pixel != (unsigned char)buffer->drawOpts.colorKey))
            {
                // DF_ALWAYS = no depth test
                if(buffer->drawOpts.depthFunc == DF_ALWAYS)
                    gfx_drawPixel(x, y, pixel, buffer);
                else
                    gfx_drawPixelWithDepth(x, y, lerpInvZ, pixel, buffer);
            }
        }

        startX += dxLeft;
        endX   += dxRight;

        if(finished) break;
    }
}

/* ***** */
void gfx_affineTextureMap(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double x, y, invDy, dxLeft, dxRight, yDir = 1;
    int   useColorKey = buffer->drawOpts.colorKey != -1 ? 1 : 0;
    float duLeft, dvLeft, duRight, dvRight;
    float startU, startV, invDx, du, dv, startX, endX;
    float texW = t->texture->width - 1;
    float texH = t->texture->height - 1;
    int   texArea = texW * texH;
    // variables used only if depth test is enabled
    float invZ0, invZ1, invZ2, invY02 = 1.f;
    int   finished = 0;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        yDir = -1;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;

    duLeft  = texW * (v2->uv.u - v0->uv.u) * invDy;
    dvLeft  = texH * (v2->uv.v - v0->uv.v) * invDy;
    duRight = texW * (v1->uv.u - v0->uv.u) * invDy;
    dvRight = texH * (v1->uv.v - v0->uv.v) * invDy;

    startU = texW * v0->uv.u;
    startV = texH * v0->uv.v;
    // With triangles the texture gradients (u,v slopes over the triangle surface)
    // are guaranteed to be constant, so we need to calculate du and dv only once.
    invDx = 1.f / (dxRight - dxLeft);
    du = (duRight - duLeft) * invDx;
    dv = (dvRight - dvLeft) * invDx;
    startX = v0->position.x;
    endX   = startX;

    // skip the unnecessary divisions if there's no depth testing
    if(buffer->drawOpts.depthFunc != DF_ALWAYS)
    {
        invZ0  = 1.f / v0->position.z;
        invZ1  = 1.f / v1->position.z;
        invZ2  = 1.f / v2->position.z;
        invY02 = 1.f / (v0->position.y - v2->position.y);
    }

    for(y = v0->position.y; ; y += yDir)
    {
        float u = startU;
        float v = startV;
        // variables used only if depth test is enabled
        float startInvZ, endInvZ, invLineLength = 0.f;

        if(type == FLAT_BOTTOM && y > v2->position.y)
        {
            // in final iteration draw extra scanline to avoid pixel wide gaps
            u -= duLeft;
            v -= dvLeft;
            startX -= dxLeft;
            endX   -= dxRight;
            finished = 1;
        }
        else if ( type == FLAT_TOP && y < v2->position.y)
            break;

        // interpolate 1/z only if depth testing is enabled
        if(buffer->drawOpts.depthFunc != DF_ALWAYS)
        {
            float r1  = (v0->position.y - y) * invY02;
            startInvZ = LERP(invZ0, invZ2, r1);
            endInvZ   = LERP(invZ0, invZ1, r1);

            if(startX != endX)
                invLineLength = 1.f / (endX - startX);
        }

        for(x = startX; x <= endX; ++x)
        {
            // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
            unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

            if(!useColorKey || (useColorKey && pixel != (unsigned char)buffer->drawOpts.colorKey))
            {
                // DF_ALWAYS = no depth test
                if(buffer->drawOpts.depthFunc == DF_ALWAYS)
                    gfx_drawPixel(x, y, pixel, buffer);
                else
                {
                    float r = (x - startX) * invLineLength;
                    float lerpInvZ = LERP(startInvZ, endInvZ, r);
                    gfx_drawPixelWithDepth(x, y, lerpInvZ, pixel, buffer);
                }
            }
            u += du;
            v += dv;
        }

        startX += dxLeft;
        endX   += dxRight;
        startU += duLeft;
        startV += dvLeft;

        if(finished) break;
    }
}
<commit_msg>slightly tighter scanline gap handling for triangle rendering<commit_after>#include "src/fillers.h"
#include "src/utils.h"

/* ***** */
void gfx_flatFill(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double y, invDy, dxLeft, dxRight, xLeft, xRight;
    int currLine, numScanlines, yDir = 1;
    // variables used if depth test is enabled
    float startInvZ, endInvZ, invZ0, invZ1, invZ2, invY02;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.0 / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
    }
    else
    {
        invDy  = 1.0 / (v0->position.y - v2->position.y);
        yDir = -1;
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;
    xLeft   = v0->position.x;
    xRight  = xLeft;

    // skip the unnecessary divisions if there's no depth testing
    if(buffer->drawOpts.depthFunc != DF_ALWAYS)
    {
        invZ0  = 1.f / v0->position.z;
        invZ1  = 1.f / v1->position.z;
        invZ2  = 1.f / v2->position.z;
        invY02 = 1.f / (v0->position.y - v2->position.y);
    }

    for(currLine = 0, y = v0->position.y; currLine <= numScanlines; y += yDir)
    {
        // interpolate 1/z only if depth testing is enabled
        if(buffer->drawOpts.depthFunc != DF_ALWAYS)
        {
            float r1  = (v0->position.y - y) * invY02;
            startInvZ = LERP(invZ0, invZ2, r1);
            endInvZ   = LERP(invZ0, invZ1, r1);
            gfx_drawLine(xLeft, y, 1.f/startInvZ, xRight, y, 1.f/endInvZ, t->color, buffer);
        }
        else
            gfx_drawLine(xLeft, y, 0.f, xRight, y, 0.f, t->color, buffer);

        xLeft  += dxLeft;
        xRight += dxRight;

        if(++currLine == numScanlines)
        {
            xLeft -= dxLeft;
            xRight -= dxRight;
        }
    }
}

/* ***** */
void gfx_perspectiveTextureMap(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double x, y, invDy, dxLeft, dxRight, yDir = 1;
    int   useColorKey = buffer->drawOpts.colorKey != -1 ? 1 : 0;
    int   texW = t->texture->width - 1;
    int   texH = t->texture->height - 1;
    int   texArea = texW * texH;
    float startX  = v0->position.x;
    float endX    = startX;
    float invZ0, invZ1, invZ2, invY02 = 1.f;
    int   currLine, numScanlines;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.0 / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
    }
    else
    {
        invDy  = 1.0 / (v0->position.y - v2->position.y);
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
        yDir = -1;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;

    invZ0  = 1.f / v0->position.z;
    invZ1  = 1.f / v1->position.z;
    invZ2  = 1.f / v2->position.z;
    invY02 = 1.f / (v0->position.y - v2->position.y);

    for(currLine = 0, y = v0->position.y; currLine <= numScanlines; y += yDir)
    {
        float startInvZ, endInvZ, r1, invLineLength = 0.f;
        float startU = texW, startV = texH, endU = texW, endV = texH;

        r1 = (v0->position.y - y) * invY02;
        startInvZ = LERP(invZ0, invZ2, r1);
        endInvZ   = LERP(invZ0, invZ1, r1);

        startU *= LERP(v0->uv.u * invZ0, v2->uv.u * invZ2, r1);
        startV *= LERP(v0->uv.v * invZ0, v2->uv.v * invZ2, r1);
        endU   *= LERP(v0->uv.u * invZ0, v1->uv.u * invZ1, r1);
        endV   *= LERP(v0->uv.v * invZ0, v1->uv.v * invZ1, r1);

        if(startX != endX)
            invLineLength = 1.f / (endX - startX);

        for(x = startX; x <= endX; ++x)
        {
            // interpolate 1/z for each pixel in the scanline
            float r = (x - startX) * invLineLength;
            float lerpInvZ = LERP(startInvZ, endInvZ, r);
            float z = 1.f/lerpInvZ;
            float u = z * LERP(startU, endU, r);
            float v = z * LERP(startV, endV, r);

            // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
            unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

            if(!useColorKey || (useColorKey && pixel != (unsigned char)buffer->drawOpts.colorKey))
            {
                // DF_ALWAYS = no depth test
                if(buffer->drawOpts.depthFunc == DF_ALWAYS)
                    gfx_drawPixel(x, y, pixel, buffer);
                else
                    gfx_drawPixelWithDepth(x, y, lerpInvZ, pixel, buffer);
            }
        }

        startX += dxLeft;
        endX   += dxRight;

        if(++currLine == numScanlines)
        {
            startX -= dxLeft;
            endX   -= dxRight;
        }
    }
}

/* ***** */
void gfx_affineTextureMap(const gfx_Triangle *t, gfx_drawBuffer *buffer, enum TriangleType type)
{
    const gfx_Vertex *v0 = &t->vertices[0];
    const gfx_Vertex *v1 = &t->vertices[1];
    const gfx_Vertex *v2 = &t->vertices[2];
    double x, y, invDy, dxLeft, dxRight, yDir = 1;
    int   useColorKey = buffer->drawOpts.colorKey != -1 ? 1 : 0;
    float duLeft, dvLeft, duRight, dvRight;
    float startU, startV, invDx, du, dv, startX, endX;
    float texW = t->texture->width - 1;
    float texH = t->texture->height - 1;
    int   texArea = texW * texH;
    // variables used only if depth test is enabled
    float invZ0, invZ1, invZ2, invY02 = 1.f;
    int   currLine, numScanlines;

    if(type == FLAT_BOTTOM)
    {
        invDy  = 1.f / (v2->position.y - v0->position.y);
        numScanlines = ceil(v2->position.y) - ceil(v0->position.y);
    }
    else
    {
        invDy  = 1.f / (v0->position.y - v2->position.y);
        numScanlines = ceil(v0->position.y) - ceil(v2->position.y);
        yDir = -1;
    }

    dxLeft  = (v2->position.x - v0->position.x) * invDy;
    dxRight = (v1->position.x - v0->position.x) * invDy;

    duLeft  = texW * (v2->uv.u - v0->uv.u) * invDy;
    dvLeft  = texH * (v2->uv.v - v0->uv.v) * invDy;
    duRight = texW * (v1->uv.u - v0->uv.u) * invDy;
    dvRight = texH * (v1->uv.v - v0->uv.v) * invDy;

    startU = texW * v0->uv.u;
    startV = texH * v0->uv.v;
    // With triangles the texture gradients (u,v slopes over the triangle surface)
    // are guaranteed to be constant, so we need to calculate du and dv only once.
    invDx = 1.f / (dxRight - dxLeft);
    du = (duRight - duLeft) * invDx;
    dv = (dvRight - dvLeft) * invDx;
    startX = v0->position.x;
    endX   = startX;

    // skip the unnecessary divisions if there's no depth testing
    if(buffer->drawOpts.depthFunc != DF_ALWAYS)
    {
        invZ0  = 1.f / v0->position.z;
        invZ1  = 1.f / v1->position.z;
        invZ2  = 1.f / v2->position.z;
        invY02 = 1.f / (v0->position.y - v2->position.y);
    }

    for(currLine = 0, y = v0->position.y; currLine <= numScanlines ; y += yDir)
    {
        float u = startU;
        float v = startV;
        // variables used only if depth test is enabled
        float startInvZ, endInvZ, invLineLength = 0.f;

        // interpolate 1/z only if depth testing is enabled
        if(buffer->drawOpts.depthFunc != DF_ALWAYS)
        {
            float r1  = (v0->position.y - y) * invY02;
            startInvZ = LERP(invZ0, invZ2, r1);
            endInvZ   = LERP(invZ0, invZ1, r1);

            if(startX != endX)
                invLineLength = 1.f / (endX - startX);
        }

        for(x = startX; x <= endX; ++x)
        {
            // fetch texture data with a texArea modulus for proper effect in case u or v are > 1
            unsigned char pixel = t->texture->data[((int)u + ((int)v * t->texture->height)) % texArea];

            if(!useColorKey || (useColorKey && pixel != (unsigned char)buffer->drawOpts.colorKey))
            {
                // DF_ALWAYS = no depth test
                if(buffer->drawOpts.depthFunc == DF_ALWAYS)
                    gfx_drawPixel(x, y, pixel, buffer);
                else
                {
                    float r = (x - startX) * invLineLength;
                    float lerpInvZ = LERP(startInvZ, endInvZ, r);
                    gfx_drawPixelWithDepth(x, y, lerpInvZ, pixel, buffer);
                }
            }
            u += du;
            v += dv;
        }

        startX += dxLeft;
        endX   += dxRight;
        startU += duLeft;
        startV += dvLeft;

        if(++currLine == numScanlines)
        {
            startX -= dxLeft;
            endX   -= dxRight;
            startU -= duLeft;
            startV -= dvLeft;
        }
    }
}
<|endoftext|>


<commit_before>#include "bbprojectmanager.hpp"
#include "bbprojectmanagerplugin.hpp"
#include "bbprojectmanagerconstants.hpp"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/mimedatabase.h>
#include <QAction>
#include <QMessageBox>
#include <QMainWindow>
#include <QMenu>

#include <QtPlugin>

namespace BoostBuildProjectManager { namespace Internal {

BoostBuildPlugin::BoostBuildPlugin()
{
    // Create your members
}

BoostBuildPlugin::~BoostBuildPlugin()
{
    // Unregister objects from the plugin manager's object pool
    // Delete members
}

bool BoostBuildPlugin::initialize(QStringList const& arguments, QString* errorString)
{
    Q_UNUSED(arguments)

    // Register objects in the plugin manager's object pool
    // Load settings
    // Add actions to menus
    // Connect to other plugins' signals
    // In the initialize function, a plugin can be sure that the plugins it
    // depends on have initialized their members.

    QLatin1String const mimeTypes(":boostbuildproject/BoostBuildProjectManager.mimetypes.xml");
    if (!Core::MimeDatabase::addMimeTypes(mimeTypes, errorString))
        return false;

    addAutoReleasedObject(new ProjectManager);

    return true;
}

void BoostBuildPlugin::extensionsInitialized()
{
    // Retrieve objects from the plugin manager's object pool
    // In the extensionsInitialized function, a plugin can be sure that all
    // plugins that depend on it are completely initialized.
}

ExtensionSystem::IPlugin::ShutdownFlag BoostBuildPlugin::aboutToShutdown()
{
    // Save settings
    // Disconnect from signals that are not needed during shutdown
    // Hide UI (if you add UI that is not in the main window directly)
    return SynchronousShutdown;
}

}}
<commit_msg>Add BuildConfigurationFactory and BuildStepFactory to auto-released objects<commit_after>#include "bbbuildconfiguration.hpp"
#include "bbbuildstep.hpp"
#include "bbprojectmanager.hpp"
#include "bbprojectmanagerplugin.hpp"
#include "bbprojectmanagerconstants.hpp"
#include <coreplugin/icore.h>
#include <coreplugin/icontext.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/mimedatabase.h>
#include <QAction>
#include <QMessageBox>
#include <QMainWindow>
#include <QMenu>

#include <QtPlugin>

namespace BoostBuildProjectManager { namespace Internal {

BoostBuildPlugin::BoostBuildPlugin()
{
    // Create your members
}

BoostBuildPlugin::~BoostBuildPlugin()
{
    // Unregister objects from the plugin manager's object pool
    // Delete members
}

bool BoostBuildPlugin::initialize(QStringList const& arguments, QString* errorString)
{
    Q_UNUSED(arguments)

    // Register objects in the plugin manager's object pool
    // Load settings
    // Add actions to menus
    // Connect to other plugins' signals
    // In the initialize function, a plugin can be sure that the plugins it
    // depends on have initialized their members.

    QLatin1String const mimeTypes(":boostbuildproject/BoostBuildProjectManager.mimetypes.xml");
    if (!Core::MimeDatabase::addMimeTypes(mimeTypes, errorString))
        return false;

    addAutoReleasedObject(new BuildConfigurationFactory);
    addAutoReleasedObject(new BuildStepFactory);
    //TODO addAutoReleasedObject(new RunConfigurationFactory);
    addAutoReleasedObject(new ProjectManager);

    return true;
}

void BoostBuildPlugin::extensionsInitialized()
{
    // Retrieve objects from the plugin manager's object pool
    // In the extensionsInitialized function, a plugin can be sure that all
    // plugins that depend on it are completely initialized.
}

ExtensionSystem::IPlugin::ShutdownFlag BoostBuildPlugin::aboutToShutdown()
{
    // Save settings
    // Disconnect from signals that are not needed during shutdown
    // Hide UI (if you add UI that is not in the main window directly)
    return SynchronousShutdown;
}

}}
<|endoftext|>


<commit_before>/*
 * FastRPC -- Fast RPC library compatible with XML-RPC
 * Copyright (C) 2005-7  Seznam.cz, a.s.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Seznam.cz, a.s.
 * Radlicka 2, Praha 5, 15000, Czech Republic
 * http://www.seznam.cz, mailto:fastrpc@firma.seznam.cz
 *
 * FILE          $Id: frpcserverproxy.cc,v 1.11 2011-02-18 10:37:45 skeleton-golem Exp $
 *
 * DESCRIPTION
 *
 * AUTHOR
 *              Miroslav Talasek <miroslav.talasek@firma.seznam.cz>
 *
 * HISTORY
 *
 */

#include <sstream>
#include <memory>

#include <stdarg.h>

#include "frpcserverproxy.h"
#include <frpc.h>
#include <frpctreebuilder.h>
#include <frpctreefeeder.h>
#include <memory>
#include <frpcfault.h>
#include <frpcresponseerror.h>

#include <frpcstruct.h>
#include <frpcstring.h>
#include <frpcint.h>
#include <frpcbool.h>

namespace {
    FRPC::Pool_t localPool;

    int getTimeout(const FRPC::Struct_t &config, const std::string &name,
                   int defaultValue)
    {
        // get key from config and check for existence
        const FRPC::Value_t *val(config.get(name));
        if (!val) return defaultValue;

        // OK
        return FRPC::Int(*val);
    }

    FRPC::ProtocolVersion_t parseProtocolVersion(const FRPC::Struct_t &config,
                                                 const std::string &name)
    {
        std::string strver
            (FRPC::String(config.get(name, FRPC::String_t::FRPC_EMPTY)));
        // empty/undefined => current version
        if (strver.empty()) return FRPC::ProtocolVersion_t();

        // parse input
        std::istringstream is(strver);
        int major, minor;
        is >> major >> minor;

        // OK
        return FRPC::ProtocolVersion_t(major, minor);
    }

    FRPC::ServerProxy_t::Config_t configFromStruct(const FRPC::Struct_t &s)
    {
        FRPC::ServerProxy_t::Config_t config;

        config.proxyUrl = FRPC::String(s.get("proxyUrl", FRPC::String_t::FRPC_EMPTY));
        config.readTimeout = getTimeout(s, "readTimeout", 10000);
        config.writeTimeout = getTimeout(s, "writeTimeout", 1000);
        config.useBinary = FRPC::Int(s.get("transferMode", FRPC::Int_t::FRPC_ZERO));
        config.useHTTP10 = FRPC::Bool(s.get("useHTTP10", FRPC::Bool_t::FRPC_FALSE));
        config.protocolVersion = parseProtocolVersion(s, "protocolVersion");
        config.connectTimeout = getTimeout(s, "connectTimeout", 10000);
        config.keepAlive = FRPC::Bool(s.get("keepAlive", FRPC::Bool_t::FRPC_FALSE));

        return config;
    }
}

namespace FRPC {

class ServerProxyImpl_t {
public:
    ServerProxyImpl_t(const std::string &server,
                      const ServerProxy_t::Config_t &config)
        : url(server, config.proxyUrl),
          io(-1, config.readTimeout, config.writeTimeout, -1 ,-1),
          rpcTransferMode(config.useBinary), useHTTP10(config.useHTTP10),
          serverSupportedProtocols(HTTPClient_t::XML_RPC),
          protocolVersion(config.protocolVersion),
          connector(new SimpleConnectorIPv6_t(url, config.connectTimeout,
                                          config.keepAlive))
    {}

    /** Set new read timeout */
    void setReadTimeout(int timeout) {
        io.setReadTimeout(timeout);
    }

    /** Set new write timeout */
    void setWriteTimeout(int timeout) {
        io.setWriteTimeout(timeout);
    }

    /** Set new connect timeout */
    void setConnectTimeout(int timeout) {
        connector->setTimeout(timeout);
    }

    const URL_t& getURL() {
        return url;
    }

    /** Create marshaller.
     */
    Marshaller_t* createMarshaller(HTTPClient_t &client);

    /** Call method.
     */
    Value_t& call(Pool_t &pool, const std::string &methodName,
                  const Array_t &params);

    void call(DataBuilder_t &builder, const std::string &methodName,
                                 const Array_t &params);

    /** Call method with variable number of arguments.
     */
    Value_t& call(Pool_t &pool, const char *methodName, va_list args);

private:
    URL_t url;
    HTTPIO_t io;
    unsigned int rpcTransferMode;
    bool useHTTP10;
    unsigned int serverSupportedProtocols;
    ProtocolVersion_t protocolVersion;
    std::auto_ptr<Connector_t> connector;
};

Marshaller_t* ServerProxyImpl_t::createMarshaller(HTTPClient_t &client) {
    Marshaller_t *marshaller;
    switch (rpcTransferMode) {
    case ServerProxy_t::Config_t::ON_SUPPORT:
        {
            if (serverSupportedProtocols & HTTPClient_t::BINARY_RPC) {
                //using BINARY_RPC
                marshaller= Marshaller_t::create(Marshaller_t::BINARY_RPC,
                                                 client,protocolVersion);
                client.prepare(HTTPClient_t::BINARY_RPC);
            } else {
                //using XML_RPC
                marshaller = Marshaller_t::create
                    (Marshaller_t::XML_RPC,client, protocolVersion);
                client.prepare(HTTPClient_t::XML_RPC);
            }
        }
    break;

    case ServerProxy_t::Config_t::NEVER:
        {
            // never using BINARY_RPC
            marshaller= Marshaller_t::create(Marshaller_t::XML_RPC,
                                             client,protocolVersion);
            client.prepare(HTTPClient_t::XML_RPC);
        }
    break;

    case ServerProxy_t::Config_t::ALWAYS:
        {
            //using BINARY_RPC  always
            marshaller= Marshaller_t::create(Marshaller_t::BINARY_RPC,
                                             client,protocolVersion);
            client.prepare(HTTPClient_t::BINARY_RPC);
        }
    break;

    case ServerProxy_t::Config_t::ON_SUPPORT_ON_KEEP_ALIVE:
    default:
        {
            if ((serverSupportedProtocols & HTTPClient_t::XML_RPC)
                || connector->getKeepAlive() == false
                || io.socket() != -1) {
                //using XML_RPC
                marshaller= Marshaller_t::create
                    (Marshaller_t::XML_RPC,client, protocolVersion);
                client.prepare(HTTPClient_t::XML_RPC);
            } else {
                //using BINARY_RPC
                marshaller= Marshaller_t::create
                    (Marshaller_t::BINARY_RPC, client,protocolVersion);
                client.prepare(HTTPClient_t::BINARY_RPC);
            }
        }
        break;
    }

    // OK
    return marshaller;
}

ServerProxy_t::ServerProxy_t(const std::string &server, const Config_t &config)
    : sp(new ServerProxyImpl_t(server, config))
{}

ServerProxy_t::ServerProxy_t(const std::string &server, const Struct_t &config)
    : sp(new ServerProxyImpl_t(server, configFromStruct(config)))
{}

ServerProxy_t::~ServerProxy_t() {
    // get rid of implementation
}

Value_t& ServerProxyImpl_t::call(Pool_t &pool, const std::string &methodName,
                                 const Array_t &params)
{
    HTTPClient_t client(io, url, connector.get(), useHTTP10);
    TreeBuilder_t builder(pool);
    std::auto_ptr<Marshaller_t>marshaller(createMarshaller(client));
    TreeFeeder_t feeder(*marshaller);

    try {
        marshaller->packMethodCall(methodName.c_str());
        for (Array_t::const_iterator
                 iparams = params.begin(),
                 eparams = params.end();
             iparams != eparams; ++iparams) {
            feeder.feedValue(**iparams);
        }

        marshaller->flush();
    } catch (const ResponseError_t &e) {}

    client.readResponse(builder);
    serverSupportedProtocols = client.getSupportedProtocols();
    protocolVersion = client.getProtocolVersion();
    if (&(builder.getUnMarshaledData()) == 0)
        throw  Fault_t(builder.getUnMarshaledErrorNumber(),
                       builder.getUnMarshaledErrorMessage());

    // OK, return unmarshalled data
    return builder.getUnMarshaledData();
}

void ServerProxyImpl_t::call(DataBuilder_t &builder, const std::string &methodName,
                                 const Array_t &params)
{
    HTTPClient_t client(io, url, connector.get(), useHTTP10);
    std::auto_ptr<Marshaller_t>marshaller(createMarshaller(client));
    TreeFeeder_t feeder(*marshaller);

    try {
        marshaller->packMethodCall(methodName.c_str());
        for (Array_t::const_iterator
                 iparams = params.begin(),
                 eparams = params.end();
             iparams != eparams; ++iparams) {
            feeder.feedValue(**iparams);
        }

        marshaller->flush();
    } catch (const ResponseError_t &e) {}

    client.readResponse(builder);
    serverSupportedProtocols = client.getSupportedProtocols();
    protocolVersion = client.getProtocolVersion();
}

Value_t& ServerProxy_t::call(Pool_t &pool, const std::string &methodName,
                             const Array_t &params)
{
    return sp->call(pool, methodName, params);
}

Value_t& ServerProxyImpl_t::call(Pool_t &pool, const char *methodName,
                                 va_list args)
{
    HTTPClient_t client(io, url, connector.get(), useHTTP10);
    TreeBuilder_t builder(pool);
    std::auto_ptr<Marshaller_t>marshaller(createMarshaller(client));
    TreeFeeder_t feeder(*marshaller);

    try {
        marshaller->packMethodCall(methodName);

        // marshall all passed values until null pointer
        while (const Value_t *value = va_arg(args, Value_t*))
            feeder.feedValue(*value);

        marshaller->flush();
    } catch (const ResponseError_t &e) {}

    client.readResponse(builder);
    serverSupportedProtocols = client.getSupportedProtocols();
    protocolVersion = client.getProtocolVersion();
    if(&(builder.getUnMarshaledData()) == 0)
        throw  Fault_t(builder.getUnMarshaledErrorNumber(),
                       builder.getUnMarshaledErrorMessage());

    // OK, return unmarshalled data
    return builder.getUnMarshaledData();
}

namespace {
    /** Hold va_list and destroy it (via va_end) on destruction.
     */
    struct VaListHolder_t {
        VaListHolder_t(va_list &args) : args(args) {}
        ~VaListHolder_t() { va_end(args); }
        va_list &args;
    };
}

Value_t& ServerProxy_t::call(Pool_t &pool, const char *methodName, ...) {
    // get variadic arguments
    va_list args;
    va_start(args, methodName);
    VaListHolder_t argsHolder(args);

    // use implementation
    return sp->call(pool, methodName, args);
}

void ServerProxy_t::call(DataBuilder_t &builder,
        const std::string &methodName, const Array_t &params)
{
    sp->call(builder, methodName, params);
}

void ServerProxy_t::setReadTimeout(int timeout) {
    sp->setReadTimeout(timeout);
}

void ServerProxy_t::setWriteTimeout(int timeout) {
    sp->setWriteTimeout(timeout);
}

void ServerProxy_t::setConnectTimeout(int timeout) {
    sp->setConnectTimeout(timeout);
}

const URL_t& ServerProxy_t::getURL() {
    return sp->getURL();
}

} // namespace FRPC

<commit_msg>ServerProxy_t supports unix:// schema<commit_after>/*
 * FastRPC -- Fast RPC library compatible with XML-RPC
 * Copyright (C) 2005-7  Seznam.cz, a.s.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Seznam.cz, a.s.
 * Radlicka 2, Praha 5, 15000, Czech Republic
 * http://www.seznam.cz, mailto:fastrpc@firma.seznam.cz
 *
 * FILE          $Id: frpcserverproxy.cc,v 1.11 2011-02-18 10:37:45 skeleton-golem Exp $
 *
 * DESCRIPTION
 *
 * AUTHOR
 *              Miroslav Talasek <miroslav.talasek@firma.seznam.cz>
 *
 * HISTORY
 *
 */

#include <sstream>
#include <memory>

#include <stdarg.h>

#include "frpcserverproxy.h"
#include <frpc.h>
#include <frpctreebuilder.h>
#include <frpctreefeeder.h>
#include <memory>
#include <frpcfault.h>
#include <frpcresponseerror.h>

#include <frpcstruct.h>
#include <frpcstring.h>
#include <frpcint.h>
#include <frpcbool.h>

namespace {
    FRPC::Pool_t localPool;

    int getTimeout(const FRPC::Struct_t &config, const std::string &name,
                   int defaultValue)
    {
        // get key from config and check for existence
        const FRPC::Value_t *val(config.get(name));
        if (!val) return defaultValue;

        // OK
        return FRPC::Int(*val);
    }

    FRPC::ProtocolVersion_t parseProtocolVersion(const FRPC::Struct_t &config,
                                                 const std::string &name)
    {
        std::string strver
            (FRPC::String(config.get(name, FRPC::String_t::FRPC_EMPTY)));
        // empty/undefined => current version
        if (strver.empty()) return FRPC::ProtocolVersion_t();

        // parse input
        std::istringstream is(strver);
        int major, minor;
        is >> major >> minor;

        // OK
        return FRPC::ProtocolVersion_t(major, minor);
    }

    FRPC::ServerProxy_t::Config_t configFromStruct(const FRPC::Struct_t &s)
    {
        FRPC::ServerProxy_t::Config_t config;

        config.proxyUrl = FRPC::String(s.get("proxyUrl", FRPC::String_t::FRPC_EMPTY));
        config.readTimeout = getTimeout(s, "readTimeout", 10000);
        config.writeTimeout = getTimeout(s, "writeTimeout", 1000);
        config.useBinary = FRPC::Int(s.get("transferMode", FRPC::Int_t::FRPC_ZERO));
        config.useHTTP10 = FRPC::Bool(s.get("useHTTP10", FRPC::Bool_t::FRPC_FALSE));
        config.protocolVersion = parseProtocolVersion(s, "protocolVersion");
        config.connectTimeout = getTimeout(s, "connectTimeout", 10000);
        config.keepAlive = FRPC::Bool(s.get("keepAlive", FRPC::Bool_t::FRPC_FALSE));

        return config;
    }

    FRPC::Connector_t* makeConnector(
        const FRPC::URL_t &url,
        const unsigned &connectTimeout,
        const bool &keepAlive)
    {
        if (url.isUnix()) {
            return new FRPC::SimpleConnectorUnix_t(
               url, connectTimeout, keepAlive);
        }
        return new FRPC::SimpleConnectorIPv6_t(url, connectTimeout, keepAlive);
    }
}

namespace FRPC {

class ServerProxyImpl_t {
public:
    ServerProxyImpl_t(const std::string &server,
                      const ServerProxy_t::Config_t &config)
        : url(server, config.proxyUrl),
          io(-1, config.readTimeout, config.writeTimeout, -1 ,-1),
          rpcTransferMode(config.useBinary), useHTTP10(config.useHTTP10),
          serverSupportedProtocols(HTTPClient_t::XML_RPC),
          protocolVersion(config.protocolVersion),
          connector(makeConnector(url, config.connectTimeout,
                                          config.keepAlive))
    {}

    /** Set new read timeout */
    void setReadTimeout(int timeout) {
        io.setReadTimeout(timeout);
    }

    /** Set new write timeout */
    void setWriteTimeout(int timeout) {
        io.setWriteTimeout(timeout);
    }

    /** Set new connect timeout */
    void setConnectTimeout(int timeout) {
        connector->setTimeout(timeout);
    }

    const URL_t& getURL() {
        return url;
    }

    /** Create marshaller.
     */
    Marshaller_t* createMarshaller(HTTPClient_t &client);

    /** Call method.
     */
    Value_t& call(Pool_t &pool, const std::string &methodName,
                  const Array_t &params);

    void call(DataBuilder_t &builder, const std::string &methodName,
                                 const Array_t &params);

    /** Call method with variable number of arguments.
     */
    Value_t& call(Pool_t &pool, const char *methodName, va_list args);

private:
    URL_t url;
    HTTPIO_t io;
    unsigned int rpcTransferMode;
    bool useHTTP10;
    unsigned int serverSupportedProtocols;
    ProtocolVersion_t protocolVersion;
    std::auto_ptr<Connector_t> connector;
};

Marshaller_t* ServerProxyImpl_t::createMarshaller(HTTPClient_t &client) {
    Marshaller_t *marshaller;
    switch (rpcTransferMode) {
    case ServerProxy_t::Config_t::ON_SUPPORT:
        {
            if (serverSupportedProtocols & HTTPClient_t::BINARY_RPC) {
                //using BINARY_RPC
                marshaller= Marshaller_t::create(Marshaller_t::BINARY_RPC,
                                                 client,protocolVersion);
                client.prepare(HTTPClient_t::BINARY_RPC);
            } else {
                //using XML_RPC
                marshaller = Marshaller_t::create
                    (Marshaller_t::XML_RPC,client, protocolVersion);
                client.prepare(HTTPClient_t::XML_RPC);
            }
        }
    break;

    case ServerProxy_t::Config_t::NEVER:
        {
            // never using BINARY_RPC
            marshaller= Marshaller_t::create(Marshaller_t::XML_RPC,
                                             client,protocolVersion);
            client.prepare(HTTPClient_t::XML_RPC);
        }
    break;

    case ServerProxy_t::Config_t::ALWAYS:
        {
            //using BINARY_RPC  always
            marshaller= Marshaller_t::create(Marshaller_t::BINARY_RPC,
                                             client,protocolVersion);
            client.prepare(HTTPClient_t::BINARY_RPC);
        }
    break;

    case ServerProxy_t::Config_t::ON_SUPPORT_ON_KEEP_ALIVE:
    default:
        {
            if ((serverSupportedProtocols & HTTPClient_t::XML_RPC)
                || connector->getKeepAlive() == false
                || io.socket() != -1) {
                //using XML_RPC
                marshaller= Marshaller_t::create
                    (Marshaller_t::XML_RPC,client, protocolVersion);
                client.prepare(HTTPClient_t::XML_RPC);
            } else {
                //using BINARY_RPC
                marshaller= Marshaller_t::create
                    (Marshaller_t::BINARY_RPC, client,protocolVersion);
                client.prepare(HTTPClient_t::BINARY_RPC);
            }
        }
        break;
    }

    // OK
    return marshaller;
}

ServerProxy_t::ServerProxy_t(const std::string &server, const Config_t &config)
    : sp(new ServerProxyImpl_t(server, config))
{}

ServerProxy_t::ServerProxy_t(const std::string &server, const Struct_t &config)
    : sp(new ServerProxyImpl_t(server, configFromStruct(config)))
{}

ServerProxy_t::~ServerProxy_t() {
    // get rid of implementation
}

Value_t& ServerProxyImpl_t::call(Pool_t &pool, const std::string &methodName,
                                 const Array_t &params)
{
    HTTPClient_t client(io, url, connector.get(), useHTTP10);
    TreeBuilder_t builder(pool);
    std::auto_ptr<Marshaller_t>marshaller(createMarshaller(client));
    TreeFeeder_t feeder(*marshaller);

    try {
        marshaller->packMethodCall(methodName.c_str());
        for (Array_t::const_iterator
                 iparams = params.begin(),
                 eparams = params.end();
             iparams != eparams; ++iparams) {
            feeder.feedValue(**iparams);
        }

        marshaller->flush();
    } catch (const ResponseError_t &e) {}

    client.readResponse(builder);
    serverSupportedProtocols = client.getSupportedProtocols();
    protocolVersion = client.getProtocolVersion();
    if (&(builder.getUnMarshaledData()) == 0)
        throw  Fault_t(builder.getUnMarshaledErrorNumber(),
                       builder.getUnMarshaledErrorMessage());

    // OK, return unmarshalled data
    return builder.getUnMarshaledData();
}

void ServerProxyImpl_t::call(DataBuilder_t &builder, const std::string &methodName,
                                 const Array_t &params)
{
    HTTPClient_t client(io, url, connector.get(), useHTTP10);
    std::auto_ptr<Marshaller_t>marshaller(createMarshaller(client));
    TreeFeeder_t feeder(*marshaller);

    try {
        marshaller->packMethodCall(methodName.c_str());
        for (Array_t::const_iterator
                 iparams = params.begin(),
                 eparams = params.end();
             iparams != eparams; ++iparams) {
            feeder.feedValue(**iparams);
        }

        marshaller->flush();
    } catch (const ResponseError_t &e) {}

    client.readResponse(builder);
    serverSupportedProtocols = client.getSupportedProtocols();
    protocolVersion = client.getProtocolVersion();
}

Value_t& ServerProxy_t::call(Pool_t &pool, const std::string &methodName,
                             const Array_t &params)
{
    return sp->call(pool, methodName, params);
}

Value_t& ServerProxyImpl_t::call(Pool_t &pool, const char *methodName,
                                 va_list args)
{
    HTTPClient_t client(io, url, connector.get(), useHTTP10);
    TreeBuilder_t builder(pool);
    std::auto_ptr<Marshaller_t>marshaller(createMarshaller(client));
    TreeFeeder_t feeder(*marshaller);

    try {
        marshaller->packMethodCall(methodName);

        // marshall all passed values until null pointer
        while (const Value_t *value = va_arg(args, Value_t*))
            feeder.feedValue(*value);

        marshaller->flush();
    } catch (const ResponseError_t &e) {}

    client.readResponse(builder);
    serverSupportedProtocols = client.getSupportedProtocols();
    protocolVersion = client.getProtocolVersion();
    if(&(builder.getUnMarshaledData()) == 0)
        throw  Fault_t(builder.getUnMarshaledErrorNumber(),
                       builder.getUnMarshaledErrorMessage());

    // OK, return unmarshalled data
    return builder.getUnMarshaledData();
}

namespace {
    /** Hold va_list and destroy it (via va_end) on destruction.
     */
    struct VaListHolder_t {
        VaListHolder_t(va_list &args) : args(args) {}
        ~VaListHolder_t() { va_end(args); }
        va_list &args;
    };
}

Value_t& ServerProxy_t::call(Pool_t &pool, const char *methodName, ...) {
    // get variadic arguments
    va_list args;
    va_start(args, methodName);
    VaListHolder_t argsHolder(args);

    // use implementation
    return sp->call(pool, methodName, args);
}

void ServerProxy_t::call(DataBuilder_t &builder,
        const std::string &methodName, const Array_t &params)
{
    sp->call(builder, methodName, params);
}

void ServerProxy_t::setReadTimeout(int timeout) {
    sp->setReadTimeout(timeout);
}

void ServerProxy_t::setWriteTimeout(int timeout) {
    sp->setWriteTimeout(timeout);
}

void ServerProxy_t::setConnectTimeout(int timeout) {
    sp->setConnectTimeout(timeout);
}

const URL_t& ServerProxy_t::getURL() {
    return sp->getURL();
}

} // namespace FRPC

<|endoftext|>


<commit_before><commit_msg>refactored code to select reference camera<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: AGroup.cxx,v $
 *
 *  $Revision: 1.19 $
 *
 *  last change: $Author: vg $ $Date: 2007-03-26 13:56:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"

#ifndef _CONNECTIVITY_ADO_GROUP_HXX_
#include "ado/AGroup.hxx"
#endif
#ifndef _CONNECTIVITY_ADO_USERS_HXX_
#include "ado/AUsers.hxx"
#endif
#ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
#include <cppuhelper/typeprovider.hxx>
#endif
#ifndef _COMPHELPER_SEQUENCE_HXX_
#include <comphelper/sequence.hxx>
#endif

#ifndef _COM_SUN_STAR_SDBC_XROW_HPP_
#include <com/sun/star/sdbc/XRow.hpp>
#endif
#ifndef _COM_SUN_STAR_SDBC_XRESULTSET_HPP_
#include <com/sun/star/sdbc/XResultSet.hpp>
#endif
#ifndef _CONNECTIVITY_ADO_BCONNECTION_HXX_
#include "ado/AConnection.hxx"
#endif
#ifndef CONNECTIVITY_CONNECTION_HXX
#include "TConnection.hxx"
#endif

using namespace connectivity::ado;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::sdbc;
using namespace com::sun::star::sdbcx;

// -------------------------------------------------------------------------
void WpADOGroup::Create()
{
    HRESULT         hr = -1;
    ADOGroup* pGroup = NULL;
    hr = CoCreateInstance(ADOS::CLSID_ADOGROUP_25,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          ADOS::IID_ADOGROUP_25,
                          (void**)&pGroup );

    if( !FAILED( hr ) )
    {
        operator=( pGroup );
        pGroup->Release();
    }
}
// -------------------------------------------------------------------------
OAdoGroup::OAdoGroup(OCatalog* _pParent,sal_Bool _bCase,    ADOGroup* _pGroup) : OGroup_ADO(_bCase),m_pCatalog(_pParent)
{
    construct();
    if(_pGroup)
        m_aGroup = WpADOGroup(_pGroup);
    else
        m_aGroup.Create();

}
// -------------------------------------------------------------------------
OAdoGroup::OAdoGroup(OCatalog* _pParent,sal_Bool _bCase, const ::rtl::OUString& _Name) : OGroup_ADO(_Name,_bCase),m_pCatalog(_pParent)
{
    construct();
    m_aGroup.Create();
    m_aGroup.put_Name(_Name);
}
// -------------------------------------------------------------------------
void OAdoGroup::refreshUsers()
{
    TStringVector aVector;

    WpADOUsers aUsers = m_aGroup.get_Users();
    aUsers.fillElementNames(aVector);

    if(m_pUsers)
        m_pUsers->reFill(aVector);
    else
        m_pUsers = new OUsers(m_pCatalog,m_aMutex,aVector,aUsers,isCaseSensitive());
}
//--------------------------------------------------------------------------
Sequence< sal_Int8 > OAdoGroup::getUnoTunnelImplementationId()
{
    static ::cppu::OImplementationId * pId = 0;
    if (! pId)
    {
        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
        if (! pId)
        {
            static ::cppu::OImplementationId aId;
            pId = &aId;
        }
    }
    return pId->getImplementationId();
}

// com::sun::star::lang::XUnoTunnel
//------------------------------------------------------------------
sal_Int64 OAdoGroup::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
{
    return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
                ? reinterpret_cast< sal_Int64 >( this )
                : OGroup_ADO::getSomething(rId);
}

// -------------------------------------------------------------------------
void OAdoGroup::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)throw (Exception)
{
    if(m_aGroup.IsValid())
    {

        switch(nHandle)
        {
            case PROPERTY_ID_NAME:
                {
                    ::rtl::OUString aVal;
                    rValue >>= aVal;
                    m_aGroup.put_Name(aVal);
                }
                break;
        }
    }
}
// -------------------------------------------------------------------------
void OAdoGroup::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
{
    if(m_aGroup.IsValid())
    {
        switch(nHandle)
        {
            case PROPERTY_ID_NAME:
                rValue <<= m_aGroup.get_Name();
                break;
        }
    }
}
// -------------------------------------------------------------------------

sal_Int32 SAL_CALL OAdoGroup::getPrivileges( const ::rtl::OUString& objName, sal_Int32 objType ) throw(::com::sun::star::sdbc::SQLException, RuntimeException)
{
    return MapRight(m_aGroup.GetPermissions(objName,MapObjectType(objType)));
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OAdoGroup::getGrantablePrivileges( const ::rtl::OUString& objName, sal_Int32 objType ) throw(::com::sun::star::sdbc::SQLException, RuntimeException)
{
    RightsEnum eNum = m_aGroup.GetPermissions(objName,MapObjectType(objType));
    if(eNum & adRightWithGrant)
        return MapRight(eNum);
    return 0;
}
// -------------------------------------------------------------------------
void SAL_CALL OAdoGroup::grantPrivileges( const ::rtl::OUString& objName, sal_Int32 objType, sal_Int32 objPrivileges ) throw(::com::sun::star::sdbc::SQLException, RuntimeException)
{
    m_aGroup.SetPermissions(objName,MapObjectType(objType),adAccessGrant,Map2Right(objPrivileges));
}
// -------------------------------------------------------------------------
void SAL_CALL OAdoGroup::revokePrivileges( const ::rtl::OUString& objName, sal_Int32 objType, sal_Int32 objPrivileges ) throw(::com::sun::star::sdbc::SQLException, RuntimeException)
{
    m_aGroup.SetPermissions(objName,MapObjectType(objType),adAccessDeny,Map2Right(objPrivileges));
}

// -----------------------------------------------------------------------------
void SAL_CALL OAdoGroup::acquire() throw()
{
    OGroup_ADO::acquire();
}
// -----------------------------------------------------------------------------
void SAL_CALL OAdoGroup::release() throw()
{
    OGroup_ADO::release();
}
// -----------------------------------------------------------------------------

<commit_msg>INTEGRATION: CWS changefileheader (1.19.144); FILE MERGED 2008/04/01 15:08:35 thb 1.19.144.3: #i85898# Stripping all external header guards 2008/04/01 10:52:49 thb 1.19.144.2: #i85898# Stripping all external header guards 2008/03/28 15:23:26 rt 1.19.144.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: AGroup.cxx,v $
 * $Revision: 1.20 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"

#ifndef _CONNECTIVITY_ADO_GROUP_HXX_
#include "ado/AGroup.hxx"
#endif
#include "ado/AUsers.hxx"
#include <cppuhelper/typeprovider.hxx>
#include <comphelper/sequence.hxx>
#include <com/sun/star/sdbc/XRow.hpp>
#include <com/sun/star/sdbc/XResultSet.hpp>
#ifndef _CONNECTIVITY_ADO_BCONNECTION_HXX_
#include "ado/AConnection.hxx"
#endif
#include "TConnection.hxx"

using namespace connectivity::ado;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::sdbc;
using namespace com::sun::star::sdbcx;

// -------------------------------------------------------------------------
void WpADOGroup::Create()
{
    HRESULT         hr = -1;
    ADOGroup* pGroup = NULL;
    hr = CoCreateInstance(ADOS::CLSID_ADOGROUP_25,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          ADOS::IID_ADOGROUP_25,
                          (void**)&pGroup );

    if( !FAILED( hr ) )
    {
        operator=( pGroup );
        pGroup->Release();
    }
}
// -------------------------------------------------------------------------
OAdoGroup::OAdoGroup(OCatalog* _pParent,sal_Bool _bCase,    ADOGroup* _pGroup) : OGroup_ADO(_bCase),m_pCatalog(_pParent)
{
    construct();
    if(_pGroup)
        m_aGroup = WpADOGroup(_pGroup);
    else
        m_aGroup.Create();

}
// -------------------------------------------------------------------------
OAdoGroup::OAdoGroup(OCatalog* _pParent,sal_Bool _bCase, const ::rtl::OUString& _Name) : OGroup_ADO(_Name,_bCase),m_pCatalog(_pParent)
{
    construct();
    m_aGroup.Create();
    m_aGroup.put_Name(_Name);
}
// -------------------------------------------------------------------------
void OAdoGroup::refreshUsers()
{
    TStringVector aVector;

    WpADOUsers aUsers = m_aGroup.get_Users();
    aUsers.fillElementNames(aVector);

    if(m_pUsers)
        m_pUsers->reFill(aVector);
    else
        m_pUsers = new OUsers(m_pCatalog,m_aMutex,aVector,aUsers,isCaseSensitive());
}
//--------------------------------------------------------------------------
Sequence< sal_Int8 > OAdoGroup::getUnoTunnelImplementationId()
{
    static ::cppu::OImplementationId * pId = 0;
    if (! pId)
    {
        ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
        if (! pId)
        {
            static ::cppu::OImplementationId aId;
            pId = &aId;
        }
    }
    return pId->getImplementationId();
}

// com::sun::star::lang::XUnoTunnel
//------------------------------------------------------------------
sal_Int64 OAdoGroup::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException)
{
    return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(),  rId.getConstArray(), 16 ) )
                ? reinterpret_cast< sal_Int64 >( this )
                : OGroup_ADO::getSomething(rId);
}

// -------------------------------------------------------------------------
void OAdoGroup::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)throw (Exception)
{
    if(m_aGroup.IsValid())
    {

        switch(nHandle)
        {
            case PROPERTY_ID_NAME:
                {
                    ::rtl::OUString aVal;
                    rValue >>= aVal;
                    m_aGroup.put_Name(aVal);
                }
                break;
        }
    }
}
// -------------------------------------------------------------------------
void OAdoGroup::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
{
    if(m_aGroup.IsValid())
    {
        switch(nHandle)
        {
            case PROPERTY_ID_NAME:
                rValue <<= m_aGroup.get_Name();
                break;
        }
    }
}
// -------------------------------------------------------------------------

sal_Int32 SAL_CALL OAdoGroup::getPrivileges( const ::rtl::OUString& objName, sal_Int32 objType ) throw(::com::sun::star::sdbc::SQLException, RuntimeException)
{
    return MapRight(m_aGroup.GetPermissions(objName,MapObjectType(objType)));
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OAdoGroup::getGrantablePrivileges( const ::rtl::OUString& objName, sal_Int32 objType ) throw(::com::sun::star::sdbc::SQLException, RuntimeException)
{
    RightsEnum eNum = m_aGroup.GetPermissions(objName,MapObjectType(objType));
    if(eNum & adRightWithGrant)
        return MapRight(eNum);
    return 0;
}
// -------------------------------------------------------------------------
void SAL_CALL OAdoGroup::grantPrivileges( const ::rtl::OUString& objName, sal_Int32 objType, sal_Int32 objPrivileges ) throw(::com::sun::star::sdbc::SQLException, RuntimeException)
{
    m_aGroup.SetPermissions(objName,MapObjectType(objType),adAccessGrant,Map2Right(objPrivileges));
}
// -------------------------------------------------------------------------
void SAL_CALL OAdoGroup::revokePrivileges( const ::rtl::OUString& objName, sal_Int32 objType, sal_Int32 objPrivileges ) throw(::com::sun::star::sdbc::SQLException, RuntimeException)
{
    m_aGroup.SetPermissions(objName,MapObjectType(objType),adAccessDeny,Map2Right(objPrivileges));
}

// -----------------------------------------------------------------------------
void SAL_CALL OAdoGroup::acquire() throw()
{
    OGroup_ADO::acquire();
}
// -----------------------------------------------------------------------------
void SAL_CALL OAdoGroup::release() throw()
{
    OGroup_ADO::release();
}
// -----------------------------------------------------------------------------

<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS impress2 (1.1.2); FILE ADDED 2004/02/13 12:14:08 af 1.1.2.1: #i22705# Initial revision.<commit_after><|endoftext|>


<commit_before><commit_msg>integration-quickbrown-casemapping: Added tests for Hungarian strings.<commit_after><|endoftext|>


<commit_before><commit_msg>Prediction: use simple-version of move_sequence_predictor<commit_after><|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __STOUT_WINDOWS_OS_HPP__
#define __STOUT_WINDOWS_OS_HPP__

#include <direct.h>
#include <io.h>

#include <sys/utime.h>

#include <list>
#include <map>
#include <set>
#include <string>

#include <stout/duration.hpp>
#include <stout/none.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>
#include <stout/path.hpp>
#include <stout/try.hpp>
#include <stout/windows.hpp>

#include <stout/os/raw/environment.hpp>

namespace os {

/*
// Sets the value associated with the specified key in the set of
// environment variables.
inline void setenv(const std::string& key,
                   const std::string& value,
                   bool overwrite = true)
{
  UNIMPLEMENTED;
}

// Unsets the value associated with the specified key in the set of
// environment variables.
inline void unsetenv(const std::string& key)
{
  UNIMPLEMENTED;
}

// Executes a command by calling "/bin/sh -c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error (e.g., fork/exec/waitpid failed). This function
// is async signal safe. We return int instead of returning a Try
// because Try involves 'new', which is not async signal safe.
inline int system(const std::string& command)
{
  UNIMPLEMENTED;
}

// This function is a portable version of execvpe ('p' means searching
// executable from PATH and 'e' means setting environments). We add
// this function because it is not available on all systems.
//
// NOTE: This function is not thread safe. It is supposed to be used
// only after fork (when there is only one thread). This function is
// async signal safe.
inline int execvpe(const char* file, char** argv, char** envp)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> chown(
    uid_t uid,
    gid_t gid,
    const std::string& path,
    bool recursive)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> chmod(const std::string& path, int mode)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> chroot(const std::string& directory)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> mknod(
    const std::string& path,
    mode_t mode,
    dev_t dev)
{
  UNIMPLEMENTED;
}

inline Result<uid_t> getuid(const Option<std::string>& user = None())
{
  UNIMPLEMENTED;
}

inline Result<gid_t> getgid(const Option<std::string>& user = None())
{
  UNIMPLEMENTED;
}

inline Try<Nothing> su(const std::string& user)
{
  UNIMPLEMENTED;
}

inline Result<std::string> user(Option<uid_t> uid = None())
{
  UNIMPLEMENTED;
}

// Suspends execution for the given duration.
inline Try<Nothing> sleep(const Duration& duration)
{
  UNIMPLEMENTED;
}

// Returns the list of files that match the given (shell) pattern.
inline Try<std::list<std::string>> glob(const std::string& pattern)
{
  UNIMPLEMENTED;
}

// Returns the total number of cpus (cores).
inline Try<long> cpus()
{
  UNIMPLEMENTED;
}

// Returns load struct with average system loads for the last
// 1, 5 and 15 minutes respectively.
// Load values should be interpreted as usual average loads from
// uptime(1).
inline Try<Load> loadavg()
{
  UNIMPLEMENTED;
}

// Returns the total size of main and free memory.
inline Try<Memory> memory()
{
  UNIMPLEMENTED;
}

// Return the system information.
inline Try<UTSInfo> uname()
{
  UNIMPLEMENTED;
}

inline Try<std::list<Process>> processes()
{
  UNIMPLEMENTED;
}

// Overload of os::pids for filtering by groups and sessions.
// A group / session id of 0 will fitler on the group / session ID
// of the calling process.
inline Try<std::set<pid_t>> pids(Option<pid_t> group, Option<pid_t> session)
{
  UNIMPLEMENTED;
}
*/
} // namespace os {

#endif // __STOUT_WINDOWS_OS_HPP__
<commit_msg>Windows: Added `stout/os/read.hpp` include to `windows/os.hpp`.<commit_after>// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef __STOUT_WINDOWS_OS_HPP__
#define __STOUT_WINDOWS_OS_HPP__

#include <direct.h>
#include <io.h>

#include <sys/utime.h>

#include <list>
#include <map>
#include <set>
#include <string>

#include <stout/duration.hpp>
#include <stout/none.hpp>
#include <stout/nothing.hpp>
#include <stout/option.hpp>
#include <stout/path.hpp>
#include <stout/try.hpp>
#include <stout/windows.hpp>

#include <stout/os/os.hpp>
#include <stout/os/read.hpp>

#include <stout/os/raw/environment.hpp>

namespace os {

/*
// Sets the value associated with the specified key in the set of
// environment variables.
inline void setenv(const std::string& key,
                   const std::string& value,
                   bool overwrite = true)
{
  UNIMPLEMENTED;
}

// Unsets the value associated with the specified key in the set of
// environment variables.
inline void unsetenv(const std::string& key)
{
  UNIMPLEMENTED;
}

// Executes a command by calling "/bin/sh -c <command>", and returns
// after the command has been completed. Returns 0 if succeeds, and
// return -1 on error (e.g., fork/exec/waitpid failed). This function
// is async signal safe. We return int instead of returning a Try
// because Try involves 'new', which is not async signal safe.
inline int system(const std::string& command)
{
  UNIMPLEMENTED;
}

// This function is a portable version of execvpe ('p' means searching
// executable from PATH and 'e' means setting environments). We add
// this function because it is not available on all systems.
//
// NOTE: This function is not thread safe. It is supposed to be used
// only after fork (when there is only one thread). This function is
// async signal safe.
inline int execvpe(const char* file, char** argv, char** envp)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> chown(
    uid_t uid,
    gid_t gid,
    const std::string& path,
    bool recursive)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> chmod(const std::string& path, int mode)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> chroot(const std::string& directory)
{
  UNIMPLEMENTED;
}

inline Try<Nothing> mknod(
    const std::string& path,
    mode_t mode,
    dev_t dev)
{
  UNIMPLEMENTED;
}

inline Result<uid_t> getuid(const Option<std::string>& user = None())
{
  UNIMPLEMENTED;
}

inline Result<gid_t> getgid(const Option<std::string>& user = None())
{
  UNIMPLEMENTED;
}

inline Try<Nothing> su(const std::string& user)
{
  UNIMPLEMENTED;
}

inline Result<std::string> user(Option<uid_t> uid = None())
{
  UNIMPLEMENTED;
}

// Suspends execution for the given duration.
inline Try<Nothing> sleep(const Duration& duration)
{
  UNIMPLEMENTED;
}

// Returns the list of files that match the given (shell) pattern.
inline Try<std::list<std::string>> glob(const std::string& pattern)
{
  UNIMPLEMENTED;
}

// Returns the total number of cpus (cores).
inline Try<long> cpus()
{
  UNIMPLEMENTED;
}

// Returns load struct with average system loads for the last
// 1, 5 and 15 minutes respectively.
// Load values should be interpreted as usual average loads from
// uptime(1).
inline Try<Load> loadavg()
{
  UNIMPLEMENTED;
}

// Returns the total size of main and free memory.
inline Try<Memory> memory()
{
  UNIMPLEMENTED;
}

// Return the system information.
inline Try<UTSInfo> uname()
{
  UNIMPLEMENTED;
}

inline Try<std::list<Process>> processes()
{
  UNIMPLEMENTED;
}

// Overload of os::pids for filtering by groups and sessions.
// A group / session id of 0 will fitler on the group / session ID
// of the calling process.
inline Try<std::set<pid_t>> pids(Option<pid_t> group, Option<pid_t> session)
{
  UNIMPLEMENTED;
}
*/
} // namespace os {

#endif // __STOUT_WINDOWS_OS_HPP__
<|endoftext|>


<commit_before>/** \file    map_ddc_and_rvk_to_ixtheo_notations.cc
 *  \brief   Map certain DDC and RVK categories to ixTheo notations and add them to field 652a.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2015, Library of the University of Tübingen

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

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

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
#include <unordered_map>
#include <cctype>
#include <cstdlib>
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "util.h"

void Usage() {
    std::cerr << "Usage: " << progname << " [--verbose] marc_input marc_output ddc_to_ixtheo_notations_map "
	      << "rvk_to_ixtheo_notations_map\n";
    std::exit(EXIT_FAILURE);
}

/** \class IxTheoMapper
 *  \brief Maps from a DDC or RVK hierarchy entry to an IxTheo notation.
 */
class IxTheoMapper {
    std::string from_hierarchy_;
    std::string to_ix_theo_notation_;
    std::vector<std::string> exclusions_;
public:
    explicit IxTheoMapper(const std::vector<std::string> &map_file_line);

    /** \brief Returns an IxTheo notation if we can match "hierarchy_classification".  O/w we return the empty string. */
    std::string map(const std::string &hierarchy_classification) const;
};

IxTheoMapper::IxTheoMapper(const std::vector<std::string> &map_file_line) {
    if (map_file_line.size() < 2)
	throw std::runtime_error("in IxTheoMapper::IxTheoMapper: need at least 2 elements in \"map_file_line\"!");
    from_hierarchy_ = map_file_line[0];
    to_ix_theo_notation_ = map_file_line[1];
    std::copy(map_file_line.begin() + 2, map_file_line.end(), std::back_inserter(exclusions_));
}

std::string IxTheoMapper::map(const std::string &hierarchy_classification) const {
    if (not StringUtil::StartsWith(hierarchy_classification, from_hierarchy_))
	return "";

    for (const auto &exclusion : exclusions_) {
	if (StringUtil::StartsWith(hierarchy_classification, exclusion))
	    return "";
    }

    return to_ix_theo_notation_;
}

void LoadCSVFile(const bool verbose, const std::string &filename, std::vector<IxTheoMapper> * const mappers) {
    DSVReader csv_reader(filename);
    std::vector<std::string> csv_values;
    while (csv_reader.readLine(&csv_values))
	mappers->emplace_back(csv_values);

    if (verbose)
	std::cerr << "Read " << mappers->size() << " mappings from \"" << filename << "\".\n";
}

void UpdateIxTheoNotations(const std::vector<IxTheoMapper> &mappers, const std::vector<std::string> &orig_values,
			   std::string * const ixtheo_notations_list)
{
    std::vector<std::string> ixtheo_notations_vector;
    StringUtil::Split(*ixtheo_notations_list, ':', &ixtheo_notations_vector);
    std::set<std::string> previously_assigned_notations(std::make_move_iterator(ixtheo_notations_vector.begin()),
							std::make_move_iterator(ixtheo_notations_vector.end()));

    for (const auto &mapper : mappers) {
	for (const auto &orig_value : orig_values) {
	    const std::string mapped_value(mapper.map(orig_value));
	    if (not mapped_value.empty()
		and previously_assigned_notations.find(mapped_value) == previously_assigned_notations.end())
	    {
		if (not ixtheo_notations_list->empty())
		    *ixtheo_notations_list += ':';
		*ixtheo_notations_list += mapped_value;
		previously_assigned_notations.insert(mapped_value);
	    }
	}
    }
}

void ProcessRecords(const bool verbose, const std::shared_ptr<FILE> &input, const std::shared_ptr<FILE> &output,
		    const std::vector<IxTheoMapper> &ddc_to_ixtheo_notation_mappers,
		    const std::vector<IxTheoMapper> &/*rvk_to_ixtheo_notation_mappers*/)
{
    unsigned count(0), records_with_ixtheo_notations(0), records_with_new_notations(0), skipped_group_count(0);
    while (MarcUtil::Record record = MarcUtil::Record(input.get())) {
        ++count;

	const std::vector<DirectoryEntry> &dir_entries(record.getDirEntries());
        if (dir_entries[0].getTag() != "001")
            Error("First field is not \"001\"!");

	std::string ixtheo_notations_list(record.extractFirstSubfield("652", 'a'));
	if (not ixtheo_notations_list.empty()) {
	    ++records_with_ixtheo_notations;
	    record.write(output.get());
	    continue;
	}

	std::vector<std::string> ddc_values;
	if (record.extractSubfield("082", 'a', &ddc_values) == 0) {
	    record.write(output.get());
	    continue;
	}

	if (std::find(ddc_values.cbegin(), ddc_values.cend(), "K") != ddc_values.cend()
	    or std::find(ddc_values.cbegin(), ddc_values.cend(), "B") != ddc_values.cend())
	{
	    ++skipped_group_count;
	    continue;
	}

	// Many DDCs have superfluous backslashes which are non-standard and need to be removed before further
	// processing can take place:
	for (auto &ddc_value : ddc_values)
	    StringUtil::RemoveChars("/", &ddc_value);

	UpdateIxTheoNotations(ddc_to_ixtheo_notation_mappers, ddc_values, &ixtheo_notations_list);
	if (verbose and not ixtheo_notations_list.empty()) {
	    const std::vector<std::string> &fields(record.getFields());
	    std::cout << fields[0] << ": " << StringUtil::Join(ddc_values, ',') << " -> " << ixtheo_notations_list << '\n';
        }

/*
	std::vector<std::string> rvk_values;
	int _084_index(record.getFieldIndex("084"));
	if (_084_index != -1) {
	    const std::vector<std::string> &fields(record.getFields());
	    while (_084_index < static_cast<ssize_t>(dir_entries.size()) and dir_entries[_084_index].getTag() == "084") {
		const Subfields subfields(fields[_084_index]);
		if (subfields.hasSubfieldWithValue('2', "rvk"))
		    rvk_values.emplace_back(subfields.getFirstSubfieldValue('a'));
		++_084_index;
	    }
	}
	UpdateIxTheoNotations(rvk_to_ixtheo_notation_mappers, rvk_values, &ixtheo_notations_list);
*/

	if (not ixtheo_notations_list.empty()) {
	    ++records_with_new_notations;
	    record.insertField("652", "  ""\x1F""a" + ixtheo_notations_list);
	}

	record.write(output.get());
    }

    if (verbose) {
	std::cerr << "Read " << count << " records.\n";
	std::cerr << records_with_ixtheo_notations << " records had Ixtheo notations.\n";
	std::cerr << records_with_new_notations << " records received new Ixtheo notations.\n";
	std::cerr << skipped_group_count << " records where skipped because they were in a group that we are not interested in.\n";
    }
}

int main(int argc, char **argv) {
    progname = argv[0];

    if (argc != 5 and argc != 6)
        Usage();

    bool verbose(false);
    if (argc == 6) {
	if (std::strcmp(argv[1], "--verbose") != 0)
	    Usage();
	verbose = true;
    }

    const std::string marc_input_filename(argv[verbose ? 2 : 1]);
    std::shared_ptr<FILE> marc_input(std::fopen(marc_input_filename.c_str(), "rbm"), std::fclose);
    if (marc_input == nullptr)
        Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string marc_output_filename(argv[verbose ? 3 : 2]);
    std::shared_ptr<FILE> marc_output(std::fopen(marc_output_filename.c_str(), "wb"), std::fclose);
    if (marc_output == nullptr)
        Error("can't open \"" + marc_output_filename + "\" for writing!");

    try {
	std::vector<IxTheoMapper> ddc_to_ixtheo_notation_mappers;
	LoadCSVFile(verbose, argv[verbose ? 4 : 3], &ddc_to_ixtheo_notation_mappers);

	std::vector<IxTheoMapper> rvk_to_ixtheo_notation_mappers;
//	LoadCSVFile(verbose, argv[verbose ? 5 : 4], &rvk_to_ixtheo_notation_mappers);

	ProcessRecords(verbose, marc_input, marc_output, ddc_to_ixtheo_notation_mappers, rvk_to_ixtheo_notation_mappers);
    } catch (const std::exception &x) {
	Error("caught exception: " + std::string(x.what()));
    }
}
<commit_msg>Added a comment.<commit_after>/** \file    map_ddc_and_rvk_to_ixtheo_notations.cc
 *  \brief   Map certain DDC and RVK categories to ixTheo notations and add them to field 652a.
 *  \author  Dr. Johannes Ruscheinski
 */

/*
    Copyright (C) 2015, Library of the University of Tübingen

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

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

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <algorithm>
#include <iostream>
#include <iterator>
#include <memory>
#include <unordered_map>
#include <cctype>
#include <cstdlib>
#include "MarcUtil.h"
#include "StringUtil.h"
#include "Subfields.h"
#include "util.h"

void Usage() {
    std::cerr << "Usage: " << progname << " [--verbose] marc_input marc_output ddc_to_ixtheo_notations_map "
	      << "rvk_to_ixtheo_notations_map\n";
    std::exit(EXIT_FAILURE);
}

/** \class IxTheoMapper
 *  \brief Maps from a DDC or RVK hierarchy entry to an IxTheo notation.
 */
class IxTheoMapper {
    std::string from_hierarchy_;
    std::string to_ix_theo_notation_;
    std::vector<std::string> exclusions_;
public:
    explicit IxTheoMapper(const std::vector<std::string> &map_file_line);

    /** \brief Returns an IxTheo notation if we can match "hierarchy_classification".  O/w we return the empty string. */
    std::string map(const std::string &hierarchy_classification) const;
};

IxTheoMapper::IxTheoMapper(const std::vector<std::string> &map_file_line) {
    if (map_file_line.size() < 2)
	throw std::runtime_error("in IxTheoMapper::IxTheoMapper: need at least 2 elements in \"map_file_line\"!");
    from_hierarchy_ = map_file_line[0];
    to_ix_theo_notation_ = map_file_line[1];
    std::copy(map_file_line.begin() + 2, map_file_line.end(), std::back_inserter(exclusions_));
}

std::string IxTheoMapper::map(const std::string &hierarchy_classification) const {
    if (not StringUtil::StartsWith(hierarchy_classification, from_hierarchy_))
	return "";

    for (const auto &exclusion : exclusions_) {
	if (StringUtil::StartsWith(hierarchy_classification, exclusion))
	    return "";
    }

    return to_ix_theo_notation_;
}

void LoadCSVFile(const bool verbose, const std::string &filename, std::vector<IxTheoMapper> * const mappers) {
    DSVReader csv_reader(filename);
    std::vector<std::string> csv_values;
    while (csv_reader.readLine(&csv_values))
	mappers->emplace_back(csv_values);

    if (verbose)
	std::cerr << "Read " << mappers->size() << " mappings from \"" << filename << "\".\n";
}

void UpdateIxTheoNotations(const std::vector<IxTheoMapper> &mappers, const std::vector<std::string> &orig_values,
			   std::string * const ixtheo_notations_list)
{
    std::vector<std::string> ixtheo_notations_vector;
    StringUtil::Split(*ixtheo_notations_list, ':', &ixtheo_notations_vector);
    std::set<std::string> previously_assigned_notations(std::make_move_iterator(ixtheo_notations_vector.begin()),
							std::make_move_iterator(ixtheo_notations_vector.end()));

    for (const auto &mapper : mappers) {
	for (const auto &orig_value : orig_values) {
	    const std::string mapped_value(mapper.map(orig_value));
	    if (not mapped_value.empty()
		and previously_assigned_notations.find(mapped_value) == previously_assigned_notations.end())
	    {
		if (not ixtheo_notations_list->empty())
		    *ixtheo_notations_list += ':';
		*ixtheo_notations_list += mapped_value;
		previously_assigned_notations.insert(mapped_value);
	    }
	}
    }
}

void ProcessRecords(const bool verbose, const std::shared_ptr<FILE> &input, const std::shared_ptr<FILE> &output,
		    const std::vector<IxTheoMapper> &ddc_to_ixtheo_notation_mappers,
		    const std::vector<IxTheoMapper> &/*rvk_to_ixtheo_notation_mappers*/)
{
    unsigned count(0), records_with_ixtheo_notations(0), records_with_new_notations(0), skipped_group_count(0);
    while (MarcUtil::Record record = MarcUtil::Record(input.get())) {
        ++count;

	const std::vector<DirectoryEntry> &dir_entries(record.getDirEntries());
        if (dir_entries[0].getTag() != "001")
            Error("First field is not \"001\"!");

	std::string ixtheo_notations_list(record.extractFirstSubfield("652", 'a'));
	if (not ixtheo_notations_list.empty()) {
	    ++records_with_ixtheo_notations;
	    record.write(output.get());
	    continue;
	}

	std::vector<std::string> ddc_values;
	if (record.extractSubfield("082", 'a', &ddc_values) == 0) {
	    record.write(output.get());
	    continue;
	}

	// "K" stands for children's literature and "B" stands for fiction, both of which we don't want to
	// import into IxTheo;
	if (std::find(ddc_values.cbegin(), ddc_values.cend(), "K") != ddc_values.cend()
	    or std::find(ddc_values.cbegin(), ddc_values.cend(), "B") != ddc_values.cend())
	{
	    ++skipped_group_count;
	    continue;
	}

	// Many DDCs have superfluous backslashes which are non-standard and need to be removed before further
	// processing can take place:
	for (auto &ddc_value : ddc_values)
	    StringUtil::RemoveChars("/", &ddc_value);

	UpdateIxTheoNotations(ddc_to_ixtheo_notation_mappers, ddc_values, &ixtheo_notations_list);
	if (verbose and not ixtheo_notations_list.empty()) {
	    const std::vector<std::string> &fields(record.getFields());
	    std::cout << fields[0] << ": " << StringUtil::Join(ddc_values, ',') << " -> " << ixtheo_notations_list << '\n';
        }

/*
	std::vector<std::string> rvk_values;
	int _084_index(record.getFieldIndex("084"));
	if (_084_index != -1) {
	    const std::vector<std::string> &fields(record.getFields());
	    while (_084_index < static_cast<ssize_t>(dir_entries.size()) and dir_entries[_084_index].getTag() == "084") {
		const Subfields subfields(fields[_084_index]);
		if (subfields.hasSubfieldWithValue('2', "rvk"))
		    rvk_values.emplace_back(subfields.getFirstSubfieldValue('a'));
		++_084_index;
	    }
	}
	UpdateIxTheoNotations(rvk_to_ixtheo_notation_mappers, rvk_values, &ixtheo_notations_list);
*/

	if (not ixtheo_notations_list.empty()) {
	    ++records_with_new_notations;
	    record.insertField("652", "  ""\x1F""a" + ixtheo_notations_list);
	}

	record.write(output.get());
    }

    if (verbose) {
	std::cerr << "Read " << count << " records.\n";
	std::cerr << records_with_ixtheo_notations << " records had Ixtheo notations.\n";
	std::cerr << records_with_new_notations << " records received new Ixtheo notations.\n";
	std::cerr << skipped_group_count << " records where skipped because they were in a group that we are not interested in.\n";
    }
}

int main(int argc, char **argv) {
    progname = argv[0];

    if (argc != 5 and argc != 6)
        Usage();

    bool verbose(false);
    if (argc == 6) {
	if (std::strcmp(argv[1], "--verbose") != 0)
	    Usage();
	verbose = true;
    }

    const std::string marc_input_filename(argv[verbose ? 2 : 1]);
    std::shared_ptr<FILE> marc_input(std::fopen(marc_input_filename.c_str(), "rbm"), std::fclose);
    if (marc_input == nullptr)
        Error("can't open \"" + marc_input_filename + "\" for reading!");

    const std::string marc_output_filename(argv[verbose ? 3 : 2]);
    std::shared_ptr<FILE> marc_output(std::fopen(marc_output_filename.c_str(), "wb"), std::fclose);
    if (marc_output == nullptr)
        Error("can't open \"" + marc_output_filename + "\" for writing!");

    try {
	std::vector<IxTheoMapper> ddc_to_ixtheo_notation_mappers;
	LoadCSVFile(verbose, argv[verbose ? 4 : 3], &ddc_to_ixtheo_notation_mappers);

	std::vector<IxTheoMapper> rvk_to_ixtheo_notation_mappers;
//	LoadCSVFile(verbose, argv[verbose ? 5 : 4], &rvk_to_ixtheo_notation_mappers);

	ProcessRecords(verbose, marc_input, marc_output, ddc_to_ixtheo_notation_mappers, rvk_to_ixtheo_notation_mappers);
    } catch (const std::exception &x) {
	Error("caught exception: " + std::string(x.what()));
    }
}
<|endoftext|>