cannam@226: /* cannam@226: Copyright 2011-2017 David Robillard cannam@226: cannam@226: Permission to use, copy, modify, and/or distribute this software for any cannam@226: purpose with or without fee is hereby granted, provided that the above cannam@226: copyright notice and this permission notice appear in all copies. cannam@226: cannam@226: THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES cannam@226: WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF cannam@226: MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR cannam@226: ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES cannam@226: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN cannam@226: ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF cannam@226: OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. cannam@226: */ cannam@226: cannam@226: #include "serd_internal.h" cannam@226: cannam@226: static inline SerdStatus cannam@226: serd_byte_source_page(SerdByteSource* source) cannam@226: { cannam@226: source->read_head = 0; cannam@226: size_t n_read = source->read_func( cannam@226: source->file_buf, 1, source->page_size, source->stream); cannam@226: if (n_read == 0) { cannam@226: source->file_buf[0] = '\0'; cannam@226: return (source->error_func(source->stream) cannam@226: ? SERD_ERR_UNKNOWN : SERD_FAILURE); cannam@226: } else if (n_read < source->page_size) { cannam@226: source->file_buf[n_read] = '\0'; cannam@226: } cannam@226: return SERD_SUCCESS; cannam@226: } cannam@226: cannam@226: SerdStatus cannam@226: serd_byte_source_open_source(SerdByteSource* source, cannam@226: SerdSource read_func, cannam@226: SerdStreamErrorFunc error_func, cannam@226: void* stream, cannam@226: size_t page_size) cannam@226: { cannam@226: memset(source, '\0', sizeof(*source)); cannam@226: source->stream = stream; cannam@226: source->from_stream = true; cannam@226: source->page_size = page_size; cannam@226: source->error_func = error_func; cannam@226: source->read_func = read_func; cannam@226: cannam@226: if (page_size > 1) { cannam@226: source->file_buf = (uint8_t*)serd_bufalloc(page_size); cannam@226: source->read_buf = source->file_buf; cannam@226: memset(source->file_buf, '\0', page_size); cannam@226: } else { cannam@226: source->read_buf = &source->read_byte; cannam@226: } cannam@226: cannam@226: return SERD_SUCCESS; cannam@226: } cannam@226: cannam@226: SerdStatus cannam@226: serd_byte_source_prepare(SerdByteSource* source) cannam@226: { cannam@226: if (!source->prepared) { cannam@226: source->prepared = true; cannam@226: if (source->page_size > 1) { cannam@226: return serd_byte_source_page(source); cannam@226: } else if (source->from_stream) { cannam@226: return serd_byte_source_advance(source); cannam@226: } cannam@226: } cannam@226: return SERD_SUCCESS; cannam@226: } cannam@226: cannam@226: SerdStatus cannam@226: serd_byte_source_open_string(SerdByteSource* source, const uint8_t* utf8) cannam@226: { cannam@226: memset(source, '\0', sizeof(*source)); cannam@226: source->read_buf = utf8; cannam@226: source->prepared = true; cannam@226: return SERD_SUCCESS; cannam@226: } cannam@226: cannam@226: SerdStatus cannam@226: serd_byte_source_close(SerdByteSource* source) cannam@226: { cannam@226: if (source->page_size > 1) { cannam@226: free(source->file_buf); cannam@226: } cannam@226: memset(source, '\0', sizeof(*source)); cannam@226: return SERD_SUCCESS; cannam@226: } cannam@226: cannam@226: SerdStatus cannam@226: serd_byte_source_advance(SerdByteSource* source) cannam@226: { cannam@226: const bool paging = source->page_size > 1; cannam@226: SerdStatus st = SERD_SUCCESS; cannam@226: if (source->from_stream && !paging) { cannam@226: if (source->read_func(&source->read_byte, 1, 1, source->stream) == 0) { cannam@226: return (source->error_func(source->stream) cannam@226: ? SERD_ERR_UNKNOWN : SERD_FAILURE); cannam@226: } cannam@226: } else if (++source->read_head == source->page_size && paging) { cannam@226: st = serd_byte_source_page(source); cannam@226: } cannam@226: cannam@226: return st; cannam@226: }