|
|
- // Copyright 2021 Nick Brassel (@tzarc)
- // SPDX-License-Identifier: GPL-2.0-or-later
-
- #include "qp_stream.h"
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Stream API
-
- uint32_t qp_stream_read_impl(void *output_buf, uint32_t member_size, uint32_t num_members, qp_stream_t *stream) {
- uint8_t *output_ptr = (uint8_t *)output_buf;
-
- uint32_t i;
- for (i = 0; i < (num_members * member_size); ++i) {
- int16_t c = qp_stream_get(stream);
- if (c < 0) {
- break;
- }
-
- output_ptr[i] = (uint8_t)(c & 0xFF);
- }
-
- return i / member_size;
- }
-
- uint32_t qp_stream_write_impl(const void *input_buf, uint32_t member_size, uint32_t num_members, qp_stream_t *stream) {
- uint8_t *input_ptr = (uint8_t *)input_buf;
-
- uint32_t i;
- for (i = 0; i < (num_members * member_size); ++i) {
- if (!qp_stream_put(stream, input_ptr[i])) {
- break;
- }
- }
-
- return i / member_size;
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Memory streams
-
- int16_t mem_get(qp_stream_t *stream) {
- qp_memory_stream_t *s = (qp_memory_stream_t *)stream;
- if (s->position >= s->length) {
- s->is_eof = true;
- return STREAM_EOF;
- }
- return s->buffer[s->position++];
- }
-
- bool mem_put(qp_stream_t *stream, uint8_t c) {
- qp_memory_stream_t *s = (qp_memory_stream_t *)stream;
- if (s->position >= s->length) {
- s->is_eof = true;
- return false;
- }
- s->buffer[s->position++] = c;
- return true;
- }
-
- int mem_seek(qp_stream_t *stream, int32_t offset, int origin) {
- qp_memory_stream_t *s = (qp_memory_stream_t *)stream;
-
- // Handle as per fseek
- int32_t position = s->position;
- switch (origin) {
- case SEEK_SET:
- position = offset;
- break;
- case SEEK_CUR:
- position += offset;
- break;
- case SEEK_END:
- position = s->length + offset;
- break;
- default:
- return -1;
- }
-
- // If we're before the start, ignore it.
- if (position < 0) {
- return -1;
- }
-
- // If we're at the end it's okay, we only care if we're after the end for failure purposes -- as per lseek()
- if (position > s->length) {
- return -1;
- }
-
- // Update the offset
- s->position = position;
-
- // Successful invocation of fseek() results in clearing of the EOF flag by default, mirror the same functionality
- s->is_eof = false;
-
- return 0;
- }
-
- int32_t mem_tell(qp_stream_t *stream) {
- qp_memory_stream_t *s = (qp_memory_stream_t *)stream;
- return s->position;
- }
-
- bool mem_is_eof(qp_stream_t *stream) {
- qp_memory_stream_t *s = (qp_memory_stream_t *)stream;
- return s->is_eof;
- }
-
- qp_memory_stream_t qp_make_memory_stream(void *buffer, int32_t length) {
- qp_memory_stream_t stream = {
- .base =
- {
- .get = mem_get,
- .put = mem_put,
- .seek = mem_seek,
- .tell = mem_tell,
- .is_eof = mem_is_eof,
- },
- .buffer = (uint8_t *)buffer,
- .length = length,
- .position = 0,
- };
- return stream;
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // FILE streams
-
- #ifdef QP_STREAM_HAS_FILE_IO
-
- int16_t file_get(qp_stream_t *stream) {
- qp_file_stream_t *s = (qp_file_stream_t *)stream;
- int c = fgetc(s->file);
- if (c < 0 || feof(s->file)) return STREAM_EOF;
- return (uint16_t)c;
- }
-
- bool file_put(qp_stream_t *stream, uint8_t c) {
- qp_file_stream_t *s = (qp_file_stream_t *)stream;
- return fputc(c, s->file) == c;
- }
-
- int file_seek(qp_stream_t *stream, int32_t offset, int origin) {
- qp_file_stream_t *s = (qp_file_stream_t *)stream;
- return fseek(s->file, offset, origin);
- }
-
- int32_t file_tell(qp_stream_t *stream) {
- qp_file_stream_t *s = (qp_file_stream_t *)stream;
- return (int32_t)ftell(s->file);
- }
-
- bool file_is_eof(qp_stream_t *stream) {
- qp_file_stream_t *s = (qp_file_stream_t *)stream;
- return (bool)feof(s->file);
- }
-
- qp_file_stream_t qp_make_file_stream(FILE *f) {
- qp_file_stream_t stream = {
- .base =
- {
- .get = file_get,
- .put = file_put,
- .seek = file_seek,
- .tell = file_tell,
- .is_eof = file_is_eof,
- },
- .file = f,
- };
- return stream;
- }
- #endif // QP_STREAM_HAS_FILE_IO
|