Compile fixes.
[SquirrelJME.git] / nanocoat / lib / base / seekable.c
blob0bf2fcd81715b61a3b64732134945d29e7b0da73
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/seekable.h"
13 #include "sjme/debug.h"
14 #include "sjme/closeable.h"
16 static sjme_errorCode sjme_seekable_closeHandler(
17 sjme_attrInNotNull sjme_closeable closeable)
19 sjme_seekable seekable;
21 /* Recover seekable. */
22 seekable = (sjme_seekable)closeable;
23 if (seekable == NULL)
24 return SJME_ERROR_NULL_ARGUMENTS;
26 /* Forward to close handler. */
27 if (seekable->functions->close != NULL)
28 return seekable->functions->close(seekable,
29 &seekable->implState);
31 /* No handler, just success. */
32 return SJME_ERROR_NONE;
35 sjme_errorCode sjme_seekable_open(
36 sjme_attrInNotNull sjme_alloc_pool* inPool,
37 sjme_attrOutNotNull sjme_seekable* outSeekable,
38 sjme_attrInNotNull const sjme_seekable_functions* inFunctions,
39 sjme_attrInNullable sjme_pointer data,
40 sjme_attrInNullable const sjme_frontEnd* copyFrontEnd)
42 sjme_errorCode error;
43 sjme_seekable result;
45 if (inPool == NULL || outSeekable == NULL || inFunctions == NULL)
46 return SJME_ERROR_NULL_ARGUMENTS;
48 /* These are required. */
49 if (inFunctions->size == NULL ||
50 inFunctions->read == NULL ||
51 inFunctions->init == NULL ||
52 inFunctions->close == NULL)
53 return SJME_ERROR_NOT_IMPLEMENTED;
55 /* Setup result. */
56 result = NULL;
57 if (sjme_error_is(error = sjme_alloc_weakNew(inPool,
58 sizeof(*result), sjme_closeable_autoEnqueue, NULL,
59 (void**)&result, NULL)) || result == NULL)
60 return sjme_error_default(error);
62 /* Copy in details. */
63 result->inPool = inPool;
64 result->closable.closeHandler = sjme_seekable_closeHandler;
65 result->functions = inFunctions;
66 if (copyFrontEnd != NULL)
67 memmove(&result->frontEnd,
68 copyFrontEnd, sizeof(*copyFrontEnd));
70 /* Initialize. */
71 if (sjme_error_is(error = result->functions->init(result,
72 &result->implState, data)))
74 /* Free before failing. */
75 sjme_alloc_free(result);
77 return sjme_error_default(error);
80 /* Success! */
81 *outSeekable = result;
82 return SJME_ERROR_NONE;
85 sjme_errorCode sjme_seekable_openSeekable(
86 sjme_attrInNotNull sjme_alloc_pool* inPool,
87 sjme_attrInNotNull sjme_seekable inSeekable,
88 sjme_attrOutNotNull sjme_seekable* outSeekable,
89 sjme_attrInPositive sjme_jint base,
90 sjme_attrInPositive sjme_jint length)
92 if (inPool == NULL || inSeekable == NULL || outSeekable == NULL)
93 return SJME_ERROR_NULL_ARGUMENTS;
95 if (base < 0 || length < 0 || (base + length) < 0)
96 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
98 sjme_todo("Implement this?");
99 return sjme_error_notImplemented(0);
102 sjme_errorCode sjme_seekable_read(
103 sjme_attrInNotNull sjme_seekable seekable,
104 sjme_attrOutNotNull sjme_buffer outBuf,
105 sjme_attrInPositive sjme_jint seekBase,
106 sjme_attrInPositive sjme_jint length)
108 sjme_errorCode error;
110 if (seekable == NULL || outBuf == NULL)
111 return SJME_ERROR_NONE;
113 if (seekBase < 0 || length < 0 || (seekBase + length) < 0)
114 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
116 if (seekable->functions->read == NULL)
117 return SJME_ERROR_NOT_IMPLEMENTED;
119 /* Lock seekable. */
120 if (sjme_error_is(error = sjme_thread_spinLockGrab(
121 &seekable->lock)))
122 return sjme_error_default(error);
124 /* Forward read. */
125 error = seekable->functions->read(seekable,
126 &seekable->implState, outBuf, seekBase, length);
128 /* Release lock. */
129 if (sjme_error_is(sjme_thread_spinLockRelease(&seekable->lock,
130 NULL)))
131 return sjme_error_default(error);
133 /* Success? */
134 return error;
137 sjme_errorCode sjme_seekable_readReverse(
138 sjme_attrInNotNull sjme_seekable seekable,
139 sjme_attrInRange(2, 8) sjme_jint wordSize,
140 sjme_attrOutNotNull sjme_buffer outBuf,
141 sjme_attrInPositive sjme_jint seekBase,
142 sjme_attrInPositive sjme_jint length)
144 sjme_errorCode error;
145 sjme_jbyte* tempBuf;
146 sjme_jint flipBase, hi, lo, halfWord, temp;
148 if (seekable == NULL || outBuf == NULL)
149 return SJME_ERROR_NONE;
151 if (wordSize < 2 || wordSize > 8 || (wordSize & 1) != 0)
152 return SJME_ERROR_INVALID_ARGUMENT;
154 if (seekBase < 0 || length < 0 || (seekBase + length) < 0)
155 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
157 if ((length % wordSize) != 0)
158 return SJME_ERROR_UNALIGNED_ACCESS;
160 if (seekable->functions->read == NULL)
161 return SJME_ERROR_NOT_IMPLEMENTED;
163 /* Setup temporary buffer. */
164 tempBuf = sjme_alloca(length);
165 if (tempBuf == NULL)
166 return SJME_ERROR_OUT_OF_MEMORY;
167 memset(tempBuf, 0, length);
169 /* Read in data. */
170 if (sjme_error_is(error = sjme_seekable_read(seekable,
171 tempBuf, seekBase, length)))
172 return sjme_error_default(error);
174 /* Flip all the contained data. */
175 halfWord = wordSize / 2;
176 for (flipBase = 0; flipBase < length; flipBase += wordSize)
177 for (lo = 0, hi = wordSize - 1; lo < halfWord; lo++, hi--)
179 temp = tempBuf[flipBase + lo];
180 tempBuf[flipBase + lo] = tempBuf[flipBase + hi];
181 tempBuf[flipBase + hi] = temp;
184 /* Give the flipped data! */
185 memmove(outBuf, tempBuf, length);
186 return SJME_ERROR_NONE;
189 sjme_errorCode sjme_seekable_regionLock(
190 sjme_attrInNotNull sjme_seekable seekable,
191 sjme_attrOutNotNull sjme_seekable_lock* outLock,
192 sjme_attrInPositive sjme_jint base,
193 sjme_attrInPositive sjme_jint length)
195 if (seekable == NULL || outLock == NULL)
196 return SJME_ERROR_NULL_ARGUMENTS;
198 if (base < 0 || length < 0 || (base + length) < 0)
199 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
201 sjme_todo("Implement this?");
202 return sjme_error_notImplemented(0);
205 sjme_errorCode sjme_seekable_regionUnlock(
206 sjme_attrInNotNull sjme_seekable_lock inLock,
207 sjme_attrInRange(0, SJME_NUM_SEEKABLE_UNLOCK_ACTION)
208 sjme_seekable_unlockAction action)
210 if (inLock == NULL)
211 return SJME_ERROR_NULL_ARGUMENTS;
213 if (action < 0 || action >= SJME_NUM_SEEKABLE_UNLOCK_ACTION)
214 return SJME_ERROR_INVALID_ARGUMENT;
216 sjme_todo("Implement this?");
217 return sjme_error_notImplemented(0);
220 sjme_errorCode sjme_seekable_size(
221 sjme_attrInNotNull sjme_seekable seekable,
222 sjme_attrOutNotNull sjme_jint* outSize)
224 sjme_errorCode error;
225 sjme_jint size;
227 if (seekable == NULL || outSize == NULL)
228 return SJME_ERROR_NULL_ARGUMENTS;
230 if (seekable->functions->size == NULL)
231 return SJME_ERROR_NOT_IMPLEMENTED;
233 /* Lock seekable. */
234 if (sjme_error_is(error = sjme_thread_spinLockGrab(
235 &seekable->lock)))
236 return sjme_error_default(error);
238 /* Forward size call. */
239 size = -1;
240 error = seekable->functions->size(seekable,
241 &seekable->implState, &size);
243 /* Release lock. */
244 if (sjme_error_is(sjme_thread_spinLockRelease(&seekable->lock,
245 NULL)))
246 return sjme_error_default(error);
248 /* Failed? */
249 if (sjme_error_is(error) || size < 0)
250 return sjme_error_default(error);
252 /* Success! */
253 *outSize = size;
254 return SJME_ERROR_NONE;