Compile fixes.
[SquirrelJME.git] / nanocoat / lib / base / streamSeekable.c
blob45ef217425bd042ca439f7c33bc34a1c2a04b8f9
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 typedef struct sjme_stream_inputSeekableInitData
19 /** The seekable to access. */
20 sjme_seekable seekable;
22 /** The base offset. */
23 sjme_jint base;
25 /** The length of the chunk. */
26 sjme_jint length;
28 /** Forward close? */
29 sjme_jboolean forwardClose;
30 } sjme_stream_inputSeekableInitData;
32 static sjme_errorCode sjme_stream_inputSeekableAvailable(
33 sjme_attrInNotNull sjme_stream_input stream,
34 sjme_attrInNotNull sjme_stream_implState* inImplState,
35 sjme_attrOutNotNull sjme_attrOutNegativeOnePositive sjme_jint* outAvail)
37 sjme_todo("Impl?");
38 return sjme_error_notImplemented(0);
41 static sjme_errorCode sjme_stream_inputSeekableClose(
42 sjme_attrInNotNull sjme_stream_input stream,
43 sjme_attrInNotNull sjme_stream_implState* inImplState)
45 sjme_errorCode error;
47 if (stream == NULL || inImplState == NULL)
48 return SJME_ERROR_NONE;
50 /* Only forward close if it was requested. */
51 if (inImplState->forwardClose)
52 if (sjme_error_is(error = sjme_closeable_close(
53 SJME_AS_CLOSEABLE(inImplState->handle))))
54 return sjme_error_default(error);
56 /* Success! */
57 return SJME_ERROR_NONE;
60 static sjme_errorCode sjme_stream_inputSeekableInit(
61 sjme_attrInNotNull sjme_stream_input stream,
62 sjme_attrInNotNull sjme_stream_implState* inImplState,
63 sjme_attrInNullable sjme_pointer data)
65 sjme_stream_inputSeekableInitData* init;
67 init = data;
68 if (stream == NULL || inImplState == NULL || data == NULL)
69 return SJME_ERROR_NULL_ARGUMENTS;
71 /* Set parameters. */
72 inImplState->handle = init->seekable;
73 inImplState->offset = init->base;
74 inImplState->index = 0;
75 inImplState->length = init->length;
76 inImplState->forwardClose = init->forwardClose;
78 /* Success! */
79 return SJME_ERROR_NONE;
82 static sjme_errorCode sjme_stream_inputSeekableRead(
83 sjme_attrInNotNull sjme_stream_input stream,
84 sjme_attrInNotNull sjme_stream_implState* inImplState,
85 sjme_attrOutNotNull sjme_attrOutNegativeOnePositive sjme_jint* readCount,
86 sjme_attrOutNotNullBuf(length) sjme_pointer dest,
87 sjme_attrInPositive sjme_jint length)
89 sjme_seekable seekable;
90 sjme_errorCode error;
91 sjme_jint size, limit, left, readAt;
93 if (stream == NULL || inImplState == NULL || readCount == NULL ||
94 dest == NULL)
95 return SJME_ERROR_NULL_ARGUMENTS;
97 if (length < 0)
98 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
100 /* Recover seekable. */
101 seekable = inImplState->handle;
102 if (seekable == NULL)
103 return SJME_ERROR_ILLEGAL_STATE;
105 /* How much length is left? */
106 size = inImplState->length;
107 readAt = inImplState->index;
108 left = size - readAt;
110 /* Can we quickly determine EOF? */
111 if (left <= 0)
113 *readCount = -1;
114 return SJME_ERROR_NONE;
117 /* We cannot read more than what is left. */
118 limit = (length < left ? length : left);
120 /* Read in data. */
121 if (sjme_error_is(error = sjme_seekable_read(seekable,
122 dest, inImplState->offset + readAt, limit)))
123 return sjme_error_default(error);
125 /* We read exactly that. */
126 inImplState->index = readAt + limit;
127 *readCount = limit;
129 /* Success! */
130 return SJME_ERROR_NONE;
133 static const sjme_stream_inputFunctions sjme_stream_inputSeekableFunctions =
135 .available = sjme_stream_inputSeekableAvailable,
136 .init = sjme_stream_inputSeekableInit,
137 .close = sjme_stream_inputSeekableClose,
138 .read = sjme_stream_inputSeekableRead,
141 sjme_errorCode sjme_stream_inputOpenSeekable(
142 sjme_attrInNotNull sjme_seekable seekable,
143 sjme_attrOutNotNull sjme_stream_input* outStream,
144 sjme_attrInPositive sjme_jint base,
145 sjme_attrInPositive sjme_jint length,
146 sjme_attrInValue sjme_jboolean forwardClose)
148 sjme_errorCode error;
149 sjme_stream_inputSeekableInitData init;
151 if (seekable == NULL || outStream == NULL)
152 return SJME_ERROR_NULL_ARGUMENTS;
154 if (base < 0 || length < 0 || (base + length) < 0)
155 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
157 /* Setup initialize. */
158 memset(&init, 0, sizeof(init));
159 init.seekable = seekable;
160 init.base = base;
161 init.length = length;
162 init.forwardClose = forwardClose;
164 /* Open base stream. */
165 return sjme_stream_inputOpen(seekable->inPool,
166 outStream, &sjme_stream_inputSeekableFunctions,
167 &init, NULL);