#ifndef QDB_API_STREAM_H
#define QDB_API_STREAM_H

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

/*
 *
 * Official quasardb C API 2.0.02.0.1
 * c64b446 2017-10-09 19:58:02 +0000
 *
 * Copyright (c) 2009-2017, 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 {
    //! 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 ::qdb_stream_close
//! when the handle is no longer required.
//!
//! \param handle A valid handle previously initialized by ::qdb_open or
//! ::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 is successful
//! \return A ::qdb_error_t code indicating success or failure.
//! \see 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 ::qdb_stream_open
//! \return A ::qdb_error_t code indicating success or failure.
//! \see 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 ::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 ::qdb_error_t code indicating success or failure.
//! \see 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 ::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 ::qdb_error_t code indicating success or failure.
//! \see 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 ::qdb_stream_open
//! \param size A pointer to an integer that will receive the size of the
//! stream, in bytes
//! \return A ::qdb_error_t code indicating success or failure.
//! \see 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 ::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 ::qdb_error_t code indicating success or failure.
//! \see 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 ::qdb_stream_open
//! \param position An integer specifying the new cursor value.
//! \return A ::qdb_error_t code indicating success or failure.
//! \see 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 ::qdb_stream_open
//! \param position An integer specifying the index at which the stream must be
//! truncated.
//! \return A ::qdb_error_t code indicating success or failure.
//! \see 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 */
