/*
**    Name: copy.c
**
**    Date: Thu Jan 17 12:02:13 2002
**
*/

#include "ODBC.h"
#include "rmamem.h"
#include "sqlext.h"
#include "sql.h"
#include <string.h>
#include <stdio.h>

/* Bytes that may be copied between a bound RMA buffer and the caller's buffer */

int bound_capacity(int slot)
    {
    ODBCLibBoundParameter *b;

    ODBCBoundInfo *i;

    b = &odbcquerytype.boundparameters[slot];
    i = &odbcboundinfo[slot];

    if (i->isindicator || data_size(i->ctype,0) > 0)
        {
        return b->size;
        }

    if (i->bufferlength <= 0)
        {
        return 0;
        }

    return i->bufferlength < b->size ? i->bufferlength : b->size;
    }

/* Refresh the RMA copy of a bound input from the caller's buffer */

void copy_bound_input_slot(int slot)
    {
    ODBCLibBoundParameter *b;

    ODBCBoundInfo *i;

    char *source;

    char *target;

    int value;

    int len;

    int nts;

    int limit;

    b = &odbcquerytype.boundparameters[slot];
    i = &odbcboundinfo[slot];

    if (b->stmt == 0 || b->data <= 0 || b->rmadata == 0 || b->size <= 0)
        {
        return;
        }

    source = (char *)b->data;
    target = (char *)b->rmadata;

    if (i->isindicator || data_size(i->ctype,0) > 0)
        {
        memcpy(target,source,b->size);
        return;
        }

    nts = 0;
    value = 0;
    len = 0;

    if (i->indicator > 0)
        {
        value = *(int *)i->indicator;

        if (value >= 0)
            {
            len = value;
            }
        else if (value == SQL_NTS)
            {
            nts = 1;
            }
        else
            {
            return;
            }
        }
    else if (i->ctype == SQL_C_CHAR)
        {
        nts = 1;
        }
    else
        {
        len = i->bufferlength > 0 ? i->bufferlength : 0;
        }

    limit = b->size;

    if (i->bufferlength > 0 && i->bufferlength < limit)
        {
        limit = i->bufferlength;
        }

    if (nts)
        {
        for (len = 0;len < limit && len < b->size - 1 && source[len] != 0;len++)
            {
            }
        }

    if (len > limit)
        {
        len = limit;
        }

    memcpy(target,source,len);

    if (len < b->size)
        {
        target[len] = 0;
        }

    if (!nts &&
        value > len &&
        i->indslot >= 0 &&
        odbcquerytype.boundparameters[i->indslot].stmt == b->stmt &&
        odbcquerytype.boundparameters[i->indslot].rmadata != 0)
        {
        *(int *)odbcquerytype.boundparameters[i->indslot].rmadata = len;
        }
    }

/* Copy bound columns back to the caller after a fetch */

void copy_bound_parameters(int stmt)
    {
    int index;

    int len;

    for (index = 0;index < ODBCLIBMAXBOUNDPARAMETERS;index++)
        {
        if (odbcquerytype.boundparameters[index].stmt == stmt &&
            odbcquerytype.boundparameters[index].rmadata != 0 &&
            odbcquerytype.boundparameters[index].data > 0 &&
            odbcboundinfo[index].kind == ODBC_BOUND_COLUMN &&
            !odbcboundinfo[index].superseded)
            {
            len = bound_capacity(index);

            if (len > 0)
                {
                memcpy((void *)odbcquerytype.boundparameters[index].data,
                       (void *)odbcquerytype.boundparameters[index].rmadata,
                       len);
                }
            }
        }
    }

/* Refresh bound input parameters before execution */

void copy_bound_inputs(int stmt)
    {
    int index;

    int pass;

    for (pass = 1;pass >= 0;pass--)
        {
        for (index = 0;index < ODBCLIBMAXBOUNDPARAMETERS;index++)
            {
            if (odbcquerytype.boundparameters[index].stmt == stmt &&
                odbcboundinfo[index].isindicator == pass &&
                !odbcboundinfo[index].superseded &&
                (odbcboundinfo[index].kind == ODBC_BOUND_INPUT ||
                 odbcboundinfo[index].kind == ODBC_BOUND_INOUT))
                {
                copy_bound_input_slot(index);
                }
            }
        }
    }

/* Copy bound output parameters back to the caller after execution */

void copy_bound_outputs(int stmt)
    {
    int index;

    int len;

    for (index = 0;index < ODBCLIBMAXBOUNDPARAMETERS;index++)
        {
        if (odbcquerytype.boundparameters[index].stmt == stmt &&
            odbcquerytype.boundparameters[index].rmadata != 0 &&
            odbcquerytype.boundparameters[index].data > 0 &&
            !odbcboundinfo[index].superseded &&
            (odbcboundinfo[index].kind == ODBC_BOUND_OUTPUT ||
             odbcboundinfo[index].kind == ODBC_BOUND_INOUT))
            {
            len = bound_capacity(index);

            if (len > 0)
                {
                memcpy((void *)odbcquerytype.boundparameters[index].data,
                       (void *)odbcquerytype.boundparameters[index].rmadata,
                       len);
                }
            }
        }
    }
