#ifndef QDB_API_STREAM_H
#define QDB_API_STREAM_H

//! \file stream.h
//! \defgroup stream Stream operations

/*
 *
 * Official quasardb C API 3.3.0
 * b2792c2 2019-05-07 12:37:56 +0000
 *
 * Copyright (c) 2009-2019, quasardb SAS
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *    * Neither the name of quasardb nor the names of its contributors may
 *      be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY QUASARDB AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "client.h"

#ifdef __cplusplus
extern "C"
{
#endif

//! \ingroup stream
//! \typedef qdb_stream_size_t
//! \brief A cross platform integer representing a stream size or position.
#ifdef _MSC_VER
    typedef unsigned __int64 qdb_stream_size_t;
#else
#    include <stdint.h>
typedef uint64_t qdb_stream_size_t;
#endif

    //! \ingroup stream
    //! \typedef qdb_stream_t
    //! \brief An opaque stream handle
    typedef struct qdb_stream_internal * qdb_stream_t;

    //! \ingroup stream
    //! \enum qdb_stream_mode_t
    //! \brief The possible modes in which a stream may be opened
    typedef enum qdb_stream_mode_t
    {
        //! Opens the stream in read only mode
        qdb_stream_mode_read = 0,
        //! Opens the stream in read and write mode
        //! Only one client at a time may open a stream for writing
        qdb_stream_mode_append = 1,
    } qdb_stream_mode_t;

    //! \ingroup stream
    //! \brief Opens a stream in the specified mode
    //!
    //! Streams are distributed over the nodes of the cluster and have no
    //! limit in size.
    //!
    //! After the stream is opened, the cursor is positioned at the beginning
    //! of the stream.
    //!
    //! The caller must release API-allocated resources with \ref
    //! qdb_stream_close when the handle is no longer required.
    //!
    //! \param handle A valid handle previously initialized by \ref qdb_open or
    //! \ref qdb_open_tcp.
    //!
    //! \param alias A pointer to a null-terminated UTF-8 string representing
    //! the alias of the stream to open.
    //!
    //! \param mode The mode in which the stream has to be open, read or
    //! read/write
    //!
    //! \param stream A pointer to a stream handle that will be initialized if
    //!               the function returns successfully.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_stream_close
    QDB_API_LINKAGE qdb_error_t qdb_stream_open(qdb_handle_t handle,
                                                const char * alias,
                                                qdb_stream_mode_t mode,
                                                qdb_stream_t * stream);

    //! \ingroup stream
    //! \brief Closes a previously opened stream
    //!
    //! \param stream A stream handle previously initialized with \ref
    //! qdb_stream_open
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_stream_open
    QDB_API_LINKAGE qdb_error_t qdb_stream_close(qdb_stream_t stream);

    //! \ingroup stream
    //! \brief Reads data from the stream
    //!
    //! Stream are distributed over the nodes of the cluster and have no
    //! limit in size.
    //!
    //! The function will read at most \p content_length bytes from the stream
    //! and update the user-provided buffer accordingly.
    //!
    //! The cursor will be positioned just after the last byte read.
    //!
    //! If no data is available, \p content_length will be set to zero and no
    //! bytes will be read.
    //!
    //! The user-provided buffer must be large enough to receive \p
    //! content_length bytes
    //!
    //! \param stream A stream handle previously initialized with \ref
    //! qdb_stream_open
    //!
    //! \param content A pointer to a user-allocated buffer that will receive
    //! the bytes read from the stream
    //!
    //! \param content_length A pointer to an integer set by the caller to the
    //! desired amount of bytes to read from the stream. After the function
    //! complete, it will be updated by the number of bytes actually read from
    //! the stream.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_stream_open
    QDB_API_LINKAGE qdb_error_t qdb_stream_read(qdb_stream_t stream,
                                                void * content,
                                                size_t * content_length);

    //! \ingroup stream
    //! \brief Writes data to the stream
    //!
    //! Stream are distributed over the nodes of the cluster and have no
    //! limit in size.
    //!
    //! The function will write exactly the number of bytes specified by the
    //! user to the stream and position the cursor at the end of the written
    //! bytes.
    //!
    //! \param stream A stream handle previously initialized with \ref
    //! qdb_stream_open
    //!
    //! \param content A pointer to a buffer with the content to add to the
    //! stream
    //!
    //! \param content_length The size of the buffer, in bytes
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_stream_open
    QDB_API_LINKAGE qdb_error_t qdb_stream_write(qdb_stream_t stream,
                                                 const void * content,
                                                 size_t content_length);

    //! \ingroup stream
    //! \brief Retrieves the total number of bytes written in a stream
    //!
    //! \param stream A stream handle previously initialized with \ref
    //! qdb_stream_open
    //!
    //! \param size A pointer to an integer that will receive the size of the
    //! stream, in bytes.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_stream_open
    QDB_API_LINKAGE qdb_error_t qdb_stream_size(qdb_stream_t stream,
                                                qdb_stream_size_t * size);

    //! \ingroup stream
    //! \brief Retrieves the current position of the cursor within the stream.
    //!
    //! The cursor is zero-based relative to the beginning of the stream.
    //!
    //! \param stream A stream handle previously initialized with \ref
    //! qdb_stream_open
    //!
    //! \param position A pointer to an integer that will receive the position
    //! of the cursor relative to the beginning of the stream.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_stream_open
    QDB_API_LINKAGE qdb_error_t qdb_stream_getpos(qdb_stream_t stream,
                                                  qdb_stream_size_t * position);

    //! \ingroup stream
    //! \brief Sets the position of the cursor in the stream.
    //!
    //! The cursor is zero-based relative to the beginning of the stream. The
    //! cursor may not point beyond the end of the stream.
    //!
    //! \param stream A stream handle previously initialized with \ref
    //! qdb_stream_open
    //!
    //! \param position An integer specifying the new cursor value.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_stream_open
    QDB_API_LINKAGE qdb_error_t qdb_stream_setpos(qdb_stream_t stream,
                                                  qdb_stream_size_t position);

    //! \ingroup stream
    //! \brief Truncates the stream at the specified position.
    //!
    //! The position is zero-based relative to the beginning of the stream. The
    //! position may not point beyond the end of the stream.
    //!
    //! \param stream A stream handle previously initialized with \ref
    //! qdb_stream_open
    //!
    //! \param position An integer specifying the index at which the stream must
    //! be truncated.
    //!
    //! \return A \ref qdb_error_t code indicating success or failure.
    //!
    //! \see \ref qdb_stream_open
    QDB_API_LINKAGE qdb_error_t qdb_stream_truncate(qdb_stream_t stream,
                                                    qdb_stream_size_t position);

#ifdef __cplusplus
} /* extern "C" */
#endif

/* clang-format on */
#endif /* QDB_API_STREAM_H */
