cannam@226
|
1 /*
|
cannam@226
|
2 Copyright 2011-2017 David Robillard <http://drobilla.net>
|
cannam@226
|
3
|
cannam@226
|
4 Permission to use, copy, modify, and/or distribute this software for any
|
cannam@226
|
5 purpose with or without fee is hereby granted, provided that the above
|
cannam@226
|
6 copyright notice and this permission notice appear in all copies.
|
cannam@226
|
7
|
cannam@226
|
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
cannam@226
|
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
cannam@226
|
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
cannam@226
|
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
cannam@226
|
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
cannam@226
|
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
cannam@226
|
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
cannam@226
|
15 */
|
cannam@226
|
16
|
cannam@226
|
17 #include "serd_internal.h"
|
cannam@226
|
18
|
cannam@226
|
19 static inline SerdStatus
|
cannam@226
|
20 serd_byte_source_page(SerdByteSource* source)
|
cannam@226
|
21 {
|
cannam@226
|
22 source->read_head = 0;
|
cannam@226
|
23 size_t n_read = source->read_func(
|
cannam@226
|
24 source->file_buf, 1, source->page_size, source->stream);
|
cannam@226
|
25 if (n_read == 0) {
|
cannam@226
|
26 source->file_buf[0] = '\0';
|
cannam@226
|
27 return (source->error_func(source->stream)
|
cannam@226
|
28 ? SERD_ERR_UNKNOWN : SERD_FAILURE);
|
cannam@226
|
29 } else if (n_read < source->page_size) {
|
cannam@226
|
30 source->file_buf[n_read] = '\0';
|
cannam@226
|
31 }
|
cannam@226
|
32 return SERD_SUCCESS;
|
cannam@226
|
33 }
|
cannam@226
|
34
|
cannam@226
|
35 SerdStatus
|
cannam@226
|
36 serd_byte_source_open_source(SerdByteSource* source,
|
cannam@226
|
37 SerdSource read_func,
|
cannam@226
|
38 SerdStreamErrorFunc error_func,
|
cannam@226
|
39 void* stream,
|
cannam@226
|
40 size_t page_size)
|
cannam@226
|
41 {
|
cannam@226
|
42 memset(source, '\0', sizeof(*source));
|
cannam@226
|
43 source->stream = stream;
|
cannam@226
|
44 source->from_stream = true;
|
cannam@226
|
45 source->page_size = page_size;
|
cannam@226
|
46 source->error_func = error_func;
|
cannam@226
|
47 source->read_func = read_func;
|
cannam@226
|
48
|
cannam@226
|
49 if (page_size > 1) {
|
cannam@226
|
50 source->file_buf = (uint8_t*)serd_bufalloc(page_size);
|
cannam@226
|
51 source->read_buf = source->file_buf;
|
cannam@226
|
52 memset(source->file_buf, '\0', page_size);
|
cannam@226
|
53 } else {
|
cannam@226
|
54 source->read_buf = &source->read_byte;
|
cannam@226
|
55 }
|
cannam@226
|
56
|
cannam@226
|
57 return SERD_SUCCESS;
|
cannam@226
|
58 }
|
cannam@226
|
59
|
cannam@226
|
60 SerdStatus
|
cannam@226
|
61 serd_byte_source_prepare(SerdByteSource* source)
|
cannam@226
|
62 {
|
cannam@226
|
63 if (!source->prepared) {
|
cannam@226
|
64 source->prepared = true;
|
cannam@226
|
65 if (source->page_size > 1) {
|
cannam@226
|
66 return serd_byte_source_page(source);
|
cannam@226
|
67 } else if (source->from_stream) {
|
cannam@226
|
68 return serd_byte_source_advance(source);
|
cannam@226
|
69 }
|
cannam@226
|
70 }
|
cannam@226
|
71 return SERD_SUCCESS;
|
cannam@226
|
72 }
|
cannam@226
|
73
|
cannam@226
|
74 SerdStatus
|
cannam@226
|
75 serd_byte_source_open_string(SerdByteSource* source, const uint8_t* utf8)
|
cannam@226
|
76 {
|
cannam@226
|
77 memset(source, '\0', sizeof(*source));
|
cannam@226
|
78 source->read_buf = utf8;
|
cannam@226
|
79 source->prepared = true;
|
cannam@226
|
80 return SERD_SUCCESS;
|
cannam@226
|
81 }
|
cannam@226
|
82
|
cannam@226
|
83 SerdStatus
|
cannam@226
|
84 serd_byte_source_close(SerdByteSource* source)
|
cannam@226
|
85 {
|
cannam@226
|
86 if (source->page_size > 1) {
|
cannam@226
|
87 free(source->file_buf);
|
cannam@226
|
88 }
|
cannam@226
|
89 memset(source, '\0', sizeof(*source));
|
cannam@226
|
90 return SERD_SUCCESS;
|
cannam@226
|
91 }
|
cannam@226
|
92
|
cannam@226
|
93 SerdStatus
|
cannam@226
|
94 serd_byte_source_advance(SerdByteSource* source)
|
cannam@226
|
95 {
|
cannam@226
|
96 const bool paging = source->page_size > 1;
|
cannam@226
|
97 SerdStatus st = SERD_SUCCESS;
|
cannam@226
|
98 if (source->from_stream && !paging) {
|
cannam@226
|
99 if (source->read_func(&source->read_byte, 1, 1, source->stream) == 0) {
|
cannam@226
|
100 return (source->error_func(source->stream)
|
cannam@226
|
101 ? SERD_ERR_UNKNOWN : SERD_FAILURE);
|
cannam@226
|
102 }
|
cannam@226
|
103 } else if (++source->read_head == source->page_size && paging) {
|
cannam@226
|
104 st = serd_byte_source_page(source);
|
cannam@226
|
105 }
|
cannam@226
|
106
|
cannam@226
|
107 return st;
|
cannam@226
|
108 }
|