/*

  Copyright (C) 2017 Gonzalo José Carracedo Carballal

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

  You should have received a copy of the GNU Lesser General Public
  License along with this program.  If not, see
  <http://www.gnu.org/licenses/>

*/

#ifndef _SYMBUF_H
#define _SYMBUF_H

#include <util.h>
#include <sigutils/sigutils.h>

/*
 * These structures ARE NOT THREAD SAFE. They are used just for chaining
 * symbol operations (e.g. codecs) all together
 */

struct suscan_symbuf;

struct suscan_symbuf_listener {
  struct suscan_symbuf *source;
  int index; /* w.r.t listener_list */
  SUSCOUNT ptr;
  SUSDIFF (*data_func) (void *priv, const SUBITS *new_data, SUSCOUNT size);
  void    (*eos_func) (void *priv, const SUBITS *new_data, SUSCOUNT size);
  void *private;
};

typedef struct suscan_symbuf_listener suscan_symbuf_listener_t;

suscan_symbuf_listener_t *suscan_symbuf_listener_new(
    SUSDIFF (*data_func) (void *priv, const SUBITS *new_data, SUSCOUNT size),
    void    (*eos_func) (void *priv, const SUBITS *new_data, SUSCOUNT size),
    void *private);

void suscan_symbuf_listener_seek(
    suscan_symbuf_listener_t *listener,
    SUSCOUNT ptr);

SUBOOL suscan_symbuf_listener_is_plugged(
    const suscan_symbuf_listener_t *listener);

void suscan_symbuf_listener_destroy(suscan_symbuf_listener_t *listener);

struct suscan_symbuf {
  grow_buf_t buffer;
  PTR_LIST(suscan_symbuf_listener_t, listener); /* Borrowed, with holes */
};

typedef struct suscan_symbuf suscan_symbuf_t;

SUBOOL suscan_symbuf_plug_listener(
    suscan_symbuf_t *symbuf,
    suscan_symbuf_listener_t *listener);

SUBOOL suscan_symbuf_unplug_listener(
    suscan_symbuf_t *symbuf,
    suscan_symbuf_listener_t *listener);

SUBOOL suscan_symbuf_append(
    suscan_symbuf_t *symbuf,
    const SUBITS *data,
    SUSCOUNT size);

const SUBITS *suscan_symbuf_get_buffer(const suscan_symbuf_t *symbuf);

SUSCOUNT suscan_symbuf_get_size(const suscan_symbuf_t *symbuf);

suscan_symbuf_t *suscan_symbuf_new(void);

void suscan_symbuf_destroy(suscan_symbuf_t *symbuf);

#endif /* _SYMBUF_H */
