1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
12 #include "sjme/stream.h"
13 #include "sjme/alloc.h"
14 #include "sjme/debug.h"
15 #include "sjme/util.h"
18 * Stream initialization data.
22 typedef struct sjme_stream_ioInit
24 /** The base pointer to use. */
27 /** The length of the memory area. */
31 static sjme_errorCode
sjme_stream_inputMemoryAvailable(
32 sjme_attrInNotNull sjme_stream_input stream
,
33 sjme_attrInNotNull sjme_stream_implState
* inImplState
,
34 sjme_attrOutNotNull sjme_attrOutNegativeOnePositive sjme_jint
* outAvail
)
36 if (stream
== NULL
|| inImplState
== NULL
|| outAvail
== NULL
)
37 return SJME_ERROR_NULL_ARGUMENTS
;
39 /* Calculating this is trivial. */
40 *outAvail
= inImplState
->length
- stream
->totalRead
;
41 return SJME_ERROR_NONE
;
44 static sjme_errorCode
sjme_stream_inputMemoryClose(
45 sjme_attrInNotNull sjme_stream_input stream
,
46 sjme_attrInNotNull sjme_stream_implState
* inImplState
)
48 if (stream
== NULL
|| inImplState
== NULL
)
49 return SJME_ERROR_NULL_ARGUMENTS
;
51 /* Nothing needs to happen here. */
52 return SJME_ERROR_NONE
;
55 static sjme_errorCode
sjme_stream_inputMemoryInit(
56 sjme_attrInNotNull sjme_stream_input stream
,
57 sjme_attrInNotNull sjme_stream_implState
* inImplState
,
58 sjme_attrInNullable sjme_pointer data
)
60 sjme_stream_ioInit
* init
;
62 if (stream
== NULL
|| inImplState
== NULL
|| data
== NULL
)
63 return SJME_ERROR_NONE
;
65 /* Recover initializer. */
68 /* Set initial state information. */
69 inImplState
->buffer
= init
->base
;
70 inImplState
->length
= init
->length
;
73 return SJME_ERROR_NONE
;
76 static sjme_errorCode
sjme_stream_inputMemoryRead(
77 sjme_attrInNotNull sjme_stream_input stream
,
78 sjme_attrInNotNull sjme_stream_implState
* inImplState
,
79 sjme_attrOutNotNull sjme_attrOutNegativeOnePositive sjme_jint
* readCount
,
80 sjme_attrOutNotNullBuf(length
) sjme_pointer dest
,
81 sjme_attrInPositive sjme_jint length
)
85 if (stream
== NULL
|| readCount
== NULL
|| dest
== NULL
)
86 return SJME_ERROR_NULL_ARGUMENTS
;
89 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
92 if (stream
->totalRead
>= inImplState
->length
)
95 return SJME_ERROR_NONE
;
98 /* Determine how many bytes we can actually read. */
99 limit
= inImplState
->length
- stream
->totalRead
;
103 /* Do a direct memory copy. */
104 memmove(dest
, SJME_POINTER_OFFSET(inImplState
->buffer
,
105 stream
->totalRead
), limit
);
107 /* Indicate read count and consider success! */
109 return SJME_ERROR_NONE
;
112 /** Input memory functions. */
113 static const sjme_stream_inputFunctions sjme_stream_inputMemoryFunctions
=
115 .available
= sjme_stream_inputMemoryAvailable
,
116 .close
= sjme_stream_inputMemoryClose
,
117 .init
= sjme_stream_inputMemoryInit
,
118 .read
= sjme_stream_inputMemoryRead
,
121 static sjme_errorCode
sjme_stream_outputMemoryClose(
122 sjme_attrInNotNull sjme_stream_output outStream
,
123 sjme_attrInNotNull sjme_stream_implState
* inImplState
)
125 if (outStream
== NULL
|| inImplState
== NULL
)
126 return SJME_ERROR_NULL_ARGUMENTS
;
128 /* Nothing to be done here. */
129 return SJME_ERROR_NONE
;
132 static sjme_errorCode
sjme_stream_outputMemoryInit(
133 sjme_attrInNotNull sjme_stream_output stream
,
134 sjme_attrInNotNull sjme_stream_implState
* inImplState
,
135 sjme_attrInNullable sjme_pointer data
)
137 sjme_stream_ioInit
* init
;
139 if (stream
== NULL
|| inImplState
== NULL
|| data
== NULL
)
140 return SJME_ERROR_NONE
;
142 /* Recover initializer. */
145 /* Set initial state information. */
146 inImplState
->buffer
= init
->base
;
147 inImplState
->length
= init
->length
;
150 return SJME_ERROR_NONE
;
153 static sjme_errorCode
sjme_stream_outputMemoryWrite(
154 sjme_attrInNotNull sjme_stream_output stream
,
155 sjme_attrInNotNull sjme_stream_implState
* inImplState
,
156 sjme_attrInNotNull sjme_cpointer buf
,
157 sjme_attrInPositiveNonZero sjme_jint length
)
162 if (stream
== NULL
|| inImplState
== NULL
|| buf
== NULL
)
163 return SJME_ERROR_NULL_ARGUMENTS
;
165 realBuf
= (uintptr_t)buf
;
166 if (length
< 0 || realBuf
+ length
< realBuf
)
167 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
169 /* Overflowing write? */
170 written
= stream
->totalWritten
;
171 if (written
< 0 || (written
+ length
) < 0 ||
172 (written
+ length
) > inImplState
->length
)
173 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
175 /* Copy the data directly. */
176 memmove((sjme_pointer
)((uintptr_t)inImplState
->buffer
+
177 written
), buf
, length
);
180 return SJME_ERROR_NONE
;
183 static const sjme_stream_outputFunctions sjme_stream_outputMemoryFunctions
=
185 .close
= sjme_stream_outputMemoryClose
,
186 .init
= sjme_stream_outputMemoryInit
,
187 .write
= sjme_stream_outputMemoryWrite
,
190 sjme_errorCode
sjme_stream_inputOpenMemory(
191 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
192 sjme_attrOutNotNull sjme_stream_input
* outStream
,
193 sjme_attrInNotNull sjme_cpointer base
,
194 sjme_attrInPositive sjme_jint length
)
196 sjme_stream_ioInit init
;
199 if (inPool
== NULL
|| outStream
== NULL
|| base
== NULL
)
200 return SJME_ERROR_NULL_ARGUMENTS
;
202 /* Make sure memory does not overflow. */
203 realBase
= (uintptr_t)base
;
204 if (length
< 0 || (realBase
+ length
) < realBase
)
205 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
207 /* Setup initialization input. */
208 memset(&init
, 0, sizeof(init
));
210 init
.length
= length
;
212 /* Forward initialization. */
213 return sjme_stream_inputOpen(inPool
, outStream
,
214 &sjme_stream_inputMemoryFunctions
, &init
,
218 sjme_errorCode
sjme_stream_outputOpenMemory(
219 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
220 sjme_attrOutNotNull sjme_stream_output
* outStream
,
221 sjme_attrInNotNull sjme_pointer base
,
222 sjme_attrInPositive sjme_jint length
)
224 sjme_stream_ioInit init
;
227 if (inPool
== NULL
|| outStream
== NULL
|| base
== NULL
)
228 return SJME_ERROR_NULL_ARGUMENTS
;
230 /* Make sure memory does not overflow. */
231 realBase
= (uintptr_t)base
;
232 if (length
< 0 || (realBase
+ length
) < realBase
)
233 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
235 /* Setup initialization input. */
236 memset(&init
, 0, sizeof(init
));
238 init
.length
= length
;
240 /* Forward initialization. */
241 return sjme_stream_outputOpen(inPool
, outStream
,
242 &sjme_stream_outputMemoryFunctions
, &init
,