text: /*
   * Copyright (C) 2018-2020 Joseph Benden <joe@benden.us>
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
   * to deal in the Software without restriction, including without limitation
   * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   * and/or sell copies of the Software, and to permit persons to whom the
   * Software is furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   * DEALINGS IN THE SOFTWARE.
   */
  
  #ifndef AIRCRACK_UTIL_CIRCULAR_QUEUE_H
  #define AIRCRACK_UTIL_CIRCULAR_QUEUE_H
  
  #include <aircrack-ng/defs.h>
  
  /**
   * @file circular_queue.h
   *
   * @brief An implementation of a multi-threaded, blocking queue; which
   * internally uses a circular buffer for element storage.
   *
   * @author Joseph Benden <joe@benden.us>
   */
  
  #ifdef __cplusplus
  extern "C" {
  #endif
  
  /// The type representing the internal data structure for a single
  /// blocking circular queue; unaccessible to public API consumers.
  typedef struct circular_queue_t circular_queue_t;
  
  /// The type representing a handle to a single blocking circular queue.
  typedef circular_queue_t * cqueue_handle_t;
  
  /*!
   * @brief Create a new blocking circular queue.
   * @param[in] buffer A region of memory to be used for element storage.
   * @param[in] bufferSize The number of bytes available at @a buffer.
   * @param[in] elementSize The number of bytes used by a single entry stored.
   * @return A brand-new circular queue handle, else NULL on error.
   */
  API_IMPORT cqueue_handle_t circular_queue_init(uint8_t * buffer,
  											   size_t bufferSize,
  											   size_t elementSize);
  
  /*!
   * @brief Release the memory used by the circular queue.
   * @param[in] cq   The circular queue handle to operate upon.
   *
   * @par
   * The API consumer is expected to release the memory region
   * given to the @a circular_queue_init function, by themselves.
   */
  API_IMPORT void circular_queue_free(cqueue_handle_t cq);
  
  /*!
   * @brief Reset the circular queue back to its initial state.
   * @param[in] cq The circular queue handle to operate upon.
   */
  API_IMPORT void circular_queue_reset(cqueue_handle_t cq);
  
  /*!
   * @brief Store an entry to the circular queue.
   * @param[in] cq   The circular queue handle to operate upon.
   * @param[in] data A buffer location for which we copy the data in from.
   * @param[in] size The length of the @a data memory buffer. This is
   *                 permitted to be less-than or equal-to the
   *                 element size. If less-than, the remaining bytes
   *                 of the element stored are zeroed.
   *
   * @par
   * The memory location of @a data must not overlap the circular
   * queue's memory location. This is because we internally use
   * the @f memcpy function.
   */
  API_IMPORT void
  circular_queue_push(cqueue_handle_t cq, void const * const data, size_t size);
  
  /*!
   * @brief Attempts to store an entry to the circular queue, if possible.
   * @param[in] cq   The circular queue handle to operate upon.
   * @param[in] data A buffer location for which we copy the data in from.
   * @param[in] size The length of the @a data memory buffer. This is
   *                 permitted to be less-than or equal-to the
   *                 element size. If less-than, the remaining bytes
   *                 of the element stored are zeroed.
   * @return Result of operation is zero on success.
   *
   * @par
   * The memory location of @a data must not overlap the circular
   * queue's memory location. This is because we internally use
   * the @f memcpy function.
   */
  API_IMPORT int circular_queue_try_push(cqueue_handle_t cq,
  									   void const * const data,
  									   size_t size);
  
  /*!
   * @brief Acquire an entry from the circular queue.
   * @param[in] cq   The circular queue handle to operate upon.
   * @param[in] data A buffer location to which to copy the data out to.
   * @param[in] size The length of the @a data memory buffer. This is
   *                 permitted to be less-than or equal-to the
   *                 element size.
   *
   * @par
   * The memory location of @a data must not overlap the circular
   * queue's memory location. This is because we internally use
   * the @f memcpy function.
   */
  API_IMPORT void
  circular_queue_pop(cqueue_handle_t cq, void * const * data, size_t size);
  
  /*!
   * @brief Returns whether the circular queue is empty.
   * @param[in] cq The circular queue handle to operate upon.
   * @return A boolean representing the emptiness state of the
   *         circular queue.
   */
  API_IMPORT bool circular_queue_is_empty(cqueue_handle_t cq);
  
  /*!
   * @brief Returns whether the circular queue is full.
   * @param[in] cq The circular queue handle to operate upon.
   * @return A boolean representing the fullness state of the
   *         circular queue.
   */
  API_IMPORT bool circular_queue_is_full(cqueue_handle_t cq);
  
  #ifdef __cplusplus
  }
  #endif
  
  #endif
  