/*
 *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef RTC_BASE_MEMORY_FIFO_BUFFER_H_
#define RTC_BASE_MEMORY_FIFO_BUFFER_H_

#include <cstddef>
#include <cstdint>
#include <memory>

#include "api/array_view.h"
#include "api/sequence_checker.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/task_queue/task_queue_base.h"
#include "rtc_base/stream.h"
#include "rtc_base/thread_annotations.h"

namespace webrtc {

// FifoBuffer allows for efficient, thread-safe buffering of data between
// writer and reader.
class FifoBuffer final : public StreamInterface {
 public:
  // Creates a FIFO buffer with the specified capacity.
  explicit FifoBuffer(size_t length);
  // Creates a FIFO buffer with the specified capacity and owner
  FifoBuffer(size_t length, TaskQueueBase* owner);
  ~FifoBuffer() override;

  FifoBuffer(const FifoBuffer&) = delete;
  FifoBuffer& operator=(const FifoBuffer&) = delete;

  // Gets the amount of data currently readable from the buffer.
  bool GetBuffered(size_t* data_len) const;

  // StreamInterface methods
  StreamState GetState() const override;
  StreamResult Read(ArrayView<uint8_t> buffer,
                    size_t& bytes_read,
                    int& error) override;
  StreamResult Write(ArrayView<const uint8_t> buffer,
                     size_t& bytes_written,
                     int& error) override;
  void Close() override;

  // Seek to a byte offset from the beginning of the stream.  Returns false if
  // the stream does not support seeking, or cannot seek to the specified
  // position.
  bool SetPosition(size_t position);

  // Get the byte offset of the current position from the start of the stream.
  // Returns false if the position is not known.
  bool GetPosition(size_t* position) const;

  // Seek to the start of the stream.
  bool Rewind() { return SetPosition(0); }

  // GetReadData returns a pointer to a buffer which is owned by the stream.
  // The buffer contains data_len bytes.  null is returned if no data is
  // available, or if the method fails.  If the caller processes the data, it
  // must call ConsumeReadData with the number of processed bytes.  GetReadData
  // does not require a matching call to ConsumeReadData if the data is not
  // processed.  Read and ConsumeReadData invalidate the buffer returned by
  // GetReadData.
  const void* GetReadData(size_t* data_len);
  void ConsumeReadData(size_t used);
  // GetWriteBuffer returns a pointer to a buffer which is owned by the stream.
  // The buffer has a capacity of buf_len bytes.  null is returned if there is
  // no buffer available, or if the method fails.  The call may write data to
  // the buffer, and then call ConsumeWriteBuffer with the number of bytes
  // written.  GetWriteBuffer does not require a matching call to
  // ConsumeWriteData if no data is written.  Write and
  // ConsumeWriteData invalidate the buffer returned by GetWriteBuffer.
  void* GetWriteBuffer(size_t* buf_len);
  void ConsumeWriteBuffer(size_t used);

 private:
  void PostEvent(int events, int err) {
    RTC_DCHECK_RUN_ON(owner_);
    owner_->PostTask(SafeTask(task_safety_.flag(), [this, events, err]() {
      RTC_DCHECK_RUN_ON(&callback_sequence_);
      FireEvent(events, err);
    }));
  }

  // Helper method that implements Read. Caller must acquire a lock
  // when calling this method.
  StreamResult ReadLocked(void* buffer, size_t bytes, size_t* bytes_read)
      RTC_EXCLUSIVE_LOCKS_REQUIRED(callback_sequence_);

  // Helper method that implements Write. Caller must acquire a lock
  // when calling this method.
  StreamResult WriteLocked(const void* buffer,
                           size_t bytes,
                           size_t* bytes_written)
      RTC_EXCLUSIVE_LOCKS_REQUIRED(callback_sequence_);

  ScopedTaskSafety task_safety_;

  // keeps the opened/closed state of the stream
  StreamState state_ RTC_GUARDED_BY(callback_sequence_);
  // the allocated buffer
  std::unique_ptr<char[]> buffer_ RTC_GUARDED_BY(callback_sequence_);
  // size of the allocated buffer
  const size_t buffer_length_;
  // amount of readable data in the buffer
  size_t data_length_ RTC_GUARDED_BY(callback_sequence_);
  // offset to the readable data
  size_t read_position_ RTC_GUARDED_BY(callback_sequence_);
  // stream callbacks are dispatched on this thread
  TaskQueueBase* const owner_;
};

}  //  namespace webrtc


#endif  // RTC_BASE_MEMORY_FIFO_BUFFER_H_
