/*                                                             
      lcstream.h - definitions/declarations for standard processing
      of liveCache IO streams. This file extended the general 
      declaration from cpc.h of the SAPDB C/C++ Precompiler




    ========== licence begin  GPL
    Copyright (c) 1998-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end




*/
#ifndef __gpi00lcstream_h__
#define __gpi00lcstream_h__

#include <stdlib.h>
#include <livecachetypes.h>

/* returncodes for callbackfunktions */
#define SQL_STREAM_OK 0
#define SQL_STREAM_ERROR (-1)
#define SQL_STREAM_EXCEPTION (-2)
#define SQL_STREAM_NO_MORE_DATA (100)

/* Appends the oracle hostvartypes. */
#define SQL_ORA_STREAM_HANDLE 301

/*
  Applications should bind this value to ORA_T and set ORA_L
  to the number of bytes passing with  SQL_LC_StreamParm. 
  ORA_V should point to an hostvarible of the SQLStreamDesc type.
*/

typedef struct _ABAPTab {
  void* nilPointer;
  OmsTypeABAPTabHandle hABAPTab;
} ABAPTabStruct;

typedef struct _Stream {
  void* nilPointer;
  OmsTypeStreamHandle hStream;
} StreamStruct;

typedef struct _SQL_LC_StreamParm {
  union
  {
    ABAPTabStruct ABAPTab;
    StreamStruct Stream;
  }
#ifndef __cplusplus
  C_1
#endif
;
} SQL_LC_StreamParm;

#ifdef _CPC_H_1
#define SQL_PC_OLD_STREAM_SUPPORT 750
#define SQL_PC_OLD_STREAM_SUPPORT_S "7.5.0"
#if (!defined SQL_PC_VERSION) || (defined SQL_PC_VERSION && SQL_PC_VERSION <= SQL_PC_OLD_STREAM_SUPPORT)
#define SQL_CPC_OLD_LVCSTREAM 
#endif /* SQL_PC_VERSION */
#endif /* _CPC_H_1 */

/* callbackfunctions for handling stream IO */
#ifdef SQL_CPC_OLD_LVCSTREAM
/**
 * @brief Call back function for reading stream data from the client and
 *        sending it to the database.
 *
 *        The stream data is written directly to the order interface and send 
 *        to the database system. The length of the stream data is unlimited 
 *        but it will be send in pieces. For sending some pieces of data to the
 *        database the <var>SQLStreamReadProc</var> function should return
 *        #SQL_ABAP_OK for each call. For the last piece the function should 
 *        return #SQL_ABAP_NO_MORE_DATA.
 *
 * @param TabParm      [in]  The table or stream id to read from.
 * @param rgbOutStream [in]  A pointer to the buffer to where the client has  
 *                           to write the stream data.
 * @param cbStreamMax  [in]  The size in bytes of the <var>rgbOutStream</var> 
 *                           buffer.
 * @param pcbStreamLen [out] The number of bytes written to the 
 *                           <var>rgbOutStream</var> buffer.
 * @param pcbNoOfRowsRead [out] If the stream data is portioned into equal 
 *                           pieces (table rows) the client should returns the 
 *                           number of pieces written to the <var>rgbOutStream</var> buffer.
 * @return  #SQL_ABAP_OK if the <var>rgbOutStream</var> buffer was filled and 
 *          the data is ready to send. The client can send more data to the 
 *          database.
 *          #SQL_ABAP_NO_MORE_DATA if the <var>rgbOutStream</var> buffer was 
 *          filled and the stream processing should be finished.
 *          #SQL_ABAP_EXCEPTION if the call back function runs into an 
 *          unhandled exception during processing the data.
 *          Any other returncode will end the processing of the stream and send *          the returncode to the database. 
 */
typedef int (SQLStreamReadProc)(SQL_LC_StreamParm *TabParm, void *rgbOutStream, int cbStreamMax, int *pcbStreamLen, int *pcbNoOfRowsRead);

/**
 * @brief Call back function for getting stream data from database.
 *
 *        The stream data is reading directly from the order interface 
 *        and past to the call back function. 
 *        The length of the stream data is unlimited but it will be read in
 *        pieces. The function is called each time the database has send on 
 *        portion of data.
 *        The <var>SQLStreamWriteProc</var> function should return
 *        #SQL_ABAP_OK after processing the data.
 *
 * @param TabParm     [in] The table or stream id to write to.
 * @param rgbInStream [in] A pointer to the buffer from where the client has  
 *                         to read the stream data.
 * @param cbStreamMax [in] The size in bytes of the <var>rgbInStream</var> 
 *                         buffer.
 * @param cbNoRows   [out] The stream data is portioned into equal pieces
 *                          (table rows) the client has to interpret this
 *                          value to calculate the length of the 
 *                          <var>rgbInStream</var> buffer.
 *
 * @note For reading variable length of data use the extended write call back 
 *       function described later in this document.
 * @return  #SQL_ABAP_OK if the <var>rgbInStream</var> buffer was processed
 *          by the client and the next portion of data may be read from the 
 *          database.
 *          #SQL_ABAP_EXCEPTION if the call back function runs into an 
 *          unhandled exception during processing the data.
 *          Any other returncode will end the processing of the stream and send *          the returncode to the database. 
 */
typedef int (SQLStreamWriteProc)(SQL_LC_StreamParm *TabParm, void *rgbInStream, int cbNoOfRows);
#else
typedef int (SQLStreamReadProc)(SQL_LC_StreamParm *TabParm, void *rgbOutStream, int cbStreamMax, int *pcbStreamLen, int *pcbNoOfRowsRead);

typedef int (SQLStreamWriteProc)(SQL_LC_StreamParm *TabParm, void *rgbInStream, int cbNoOfRows, int cbStreamLen);
#endif

typedef struct _SQLStreamDesc {
  SQLStreamReadProc  *ReadProc;
  SQLStreamWriteProc *WriteProc;
  SQL_LC_StreamParm  *StreamParam;   
} SQLStreamDesc;


#ifdef __cplusplus
template <class T, long MCOUNT> class CStreamDescriptor : public SQLStreamDesc {
private :
    int currMember;
    void describeMember (OmsStreamTypes memberType, short length) {
        if (currMember < MCOUNT) {
            StreamParam->Stream.hStream.colDesc[currMember].memberType = memberType;
            StreamParam->Stream.hStream.colDesc[currMember].length     = length;
            if (0 == currMember) {
              StreamParam->Stream.hStream.colDesc[currMember].offset = 0;
            }
            else {
              StreamParam->Stream.hStream.colDesc[currMember].offset =
                StreamParam->Stream.hStream.colDesc[currMember-1].offset +
                StreamParam->Stream.hStream.colDesc[currMember-1].length;
            }
            currMember++;
        }
    }
public :
    CStreamDescriptor(long streamId) {
        ReadProc    = 0;
        WriteProc   = 0;
        currMember  = 0;
	if (MCOUNT == 0) {
	  /* allocate the maximum if the membercount is not set */
	  StreamParam = (SQL_LC_StreamParm*) malloc(sizeof(SQL_LC_StreamParm) - sizeof (OmsTypeStreamMemberDesc) * 256 + sizeof (OmsTypeStreamMemberDesc) * 256);
	}
	else {
	  StreamParam = (SQL_LC_StreamParm*) malloc(sizeof(SQL_LC_StreamParm) - sizeof (OmsTypeStreamMemberDesc) * 256 + sizeof (OmsTypeStreamMemberDesc) * MCOUNT);
	}
        if (StreamParam) {
            StreamParam->Stream.nilPointer          = (void*) 0;
&if $BIT64
&else
            StreamParam->Stream.hStream.reserved    = 0;
&endif
            StreamParam->Stream.hStream.ABAPTabId   = streamId;
            StreamParam->Stream.hStream.size        = sizeof(T);
            StreamParam->Stream.hStream.memberCount = MCOUNT;
        }
    }


    void Describe(short x)                   { describeMember (STYPE_I2,  sizeof(x)); }
    void Describe(unsigned short x)          { describeMember (STYPE_UI2, sizeof(x)); }
    void Describe(long x)                    { describeMember (STYPE_I4,  sizeof(x)); }
    void Describe(unsigned long x)           { describeMember (STYPE_UI4, sizeof(x)); }
    void Describe(float x)                   { describeMember (STYPE_R4,  sizeof(x)); }
    void Describe(double x)                  { describeMember (STYPE_R8,  sizeof(x)); }
    void Describe(const char* x, short size) { describeMember (STYPE_CHAR, size); }

protected :
    ~CStreamDescriptor() {
        if (StreamParam)
            free (StreamParam);
    }
};

template <class T, long MCOUNT> class COStreamDescriptor : public CStreamDescriptor<T,MCOUNT> {
public :
    COStreamDescriptor(long streamId, SQLStreamWriteProc pWriteProc) : 
        CStreamDescriptor<T,MCOUNT>(streamId) 
    {
        CStreamDescriptor<T,MCOUNT>::WriteProc = pWriteProc;
    }
};

template <class T, long MCOUNT> class CIStreamDescriptor : public CStreamDescriptor<T,MCOUNT> {
public :
    CIStreamDescriptor(long streamId, SQLStreamReadProc pReadProc) : 
        CStreamDescriptor<T,MCOUNT>(streamId) 
    {
        CStreamDescriptor<T,MCOUNT>::ReadProc = pReadProc;
    }
};

#else
#endif
#endif

