Indentations break the feed.
[SquirrelJME.git] / nanocoat / lib / base / streamMemory.c
blob3c041bac96333d0de1bce1cee0cb69dc5138fbf2
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
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 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "sjme/stream.h"
13 #include "sjme/alloc.h"
14 #include "sjme/debug.h"
15 #include "sjme/util.h"
17 /**
18 * Stream initialization data.
20 * @since 2024/08/12
22 typedef struct sjme_stream_ioInit
24 /** The base pointer to use. */
25 sjme_cpointer base;
27 /** The length of the memory area. */
28 sjme_jint length;
29 } sjme_stream_ioInit;
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. */
66 init = data;
68 /* Set initial state information. */
69 inImplState->buffer = init->base;
70 inImplState->length = init->length;
72 /* Success! */
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)
83 sjme_jint limit;
85 if (stream == NULL || readCount == NULL || dest == NULL)
86 return SJME_ERROR_NULL_ARGUMENTS;
88 if (length <= 0)
89 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
91 /* End of stream? */
92 if (stream->totalRead >= inImplState->length)
94 *readCount = -1;
95 return SJME_ERROR_NONE;
98 /* Determine how many bytes we can actually read. */
99 limit = inImplState->length - stream->totalRead;
100 if (length < limit)
101 limit = length;
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! */
108 *readCount = limit;
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. */
143 init = data;
145 /* Set initial state information. */
146 inImplState->buffer = init->base;
147 inImplState->length = init->length;
149 /* Success! */
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)
159 uintptr_t realBuf;
160 sjme_jint written;
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);
179 /* Success! */
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;
197 uintptr_t realBase;
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));
209 init.base = base;
210 init.length = length;
212 /* Forward initialization. */
213 return sjme_stream_inputOpen(inPool, outStream,
214 &sjme_stream_inputMemoryFunctions, &init,
215 NULL);
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;
225 uintptr_t realBase;
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));
237 init.base = base;
238 init.length = length;
240 /* Forward initialization. */
241 return sjme_stream_outputOpen(inPool, outStream,
242 &sjme_stream_outputMemoryFunctions, &init,
243 NULL);