ru_tts
1/* sink.c -- Interactions with general data consuming callback
2*
3* Copyright (C) 1990, 1991 Speech Research Laboratory, Minsk
4* Copyright (C) 2005 Igor Poretsky <poretsky@mlbox.ru>
5* Copyright (C) 2021 Boris Lobanov <lobbormef@gmail.com>
6* Copyright (C) 2021 Alexander Ivanov <ivalex01@gmail.com>
7*
8* SPDX-License-Identifier: MIT
9*/
10
11#include <stdint.h>12#include <stdlib.h>13#include <string.h>14
15#include "ru_tts.h"16#include "sink.h"17
18
19/* Initialize sink control structure */
20void sink_setup(sink_t *consumer, void *buffer, size_t bufsize, ru_tts_callback function, void *user_data)21{
22consumer->buffer = buffer;23consumer->buffer_offset = 0;24consumer->bufsize = bufsize;25consumer->status = 0;26consumer->user_data = user_data;27consumer->function = function;28consumer->custom_reset = NULL;29}
30
31/*
32* Reset action.
33*
34* Performs custom reset function if specified.
35* Otherwise simply resets buffer offset.
36*/
37void sink_reset(sink_t *consumer)38{
39if (consumer->custom_reset)40consumer->custom_reset(consumer);41else consumer->buffer_offset = 0;42}
43
44/* Pass data to the sink function */
45void sink_flush(sink_t *consumer)46{
47if (consumer->function && consumer->buffer && consumer->buffer_offset)48consumer->status |= consumer->function(consumer->buffer, consumer->buffer_offset, consumer->user_data);49sink_reset(consumer);50}
51
52/* Pass one byte of data */
53void sink_put(sink_t *consumer, int8_t byte)54{
55((int8_t *)(consumer->buffer))[consumer->buffer_offset++] = byte;56if (consumer->buffer_offset >= consumer->bufsize)57sink_flush(consumer);58}
59
60/*
61* Pass a block of data.
62*
63* Potentially may cause buffer overflow since this condition
64* is not checked during data transfer, but only afterwards.
65*/
66void sink_write(sink_t *consumer, const uint8_t *block, size_t size)67{
68memcpy((uint8_t *)consumer->buffer + consumer->buffer_offset, block, size);69consumer->buffer_offset += size;70if (consumer->buffer_offset >= consumer->bufsize)71sink_flush(consumer);72}
73
74/* Forget last byte if possible */
75void sink_back(sink_t *consumer)76{
77if (consumer->buffer_offset)78consumer->buffer_offset--;79}
80
81/*
82* Replace the last byte in the consumer buffer.
83* If the buffer is empty, acts just like sink_put().
84*/
85void sink_replace(sink_t *consumer, uint8_t byte)86{
87sink_back(consumer);88sink_put(consumer, byte);89}
90
91/*
92* Get last byte value from the consumer buffer.
93* Returns -1 if the buffer is empty.
94*/
95int sink_last(sink_t *consumer)96{
97return (consumer->buffer_offset) ? ((uint8_t *)(consumer->buffer))[consumer->buffer_offset - 1] : -1;98}
99