Compile fixes.
[SquirrelJME.git] / nanocoat / src / romLibrary.c
blobe237a3d4e094198aebf601e452c4e0b958696229
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/nvm/rom.h"
13 #include "sjme/alloc.h"
14 #include "sjme/debug.h"
15 #include "sjme/nvm/payload.h"
16 #include "sjme/nvm/romInternal.h"
17 #include "sjme/util.h"
18 #include "sjme/zip.h"
19 #include "sjme/cleanup.h"
21 static sjme_errorCode sjme_rom_libraryClose(
22 sjme_attrInNotNull sjme_closeable closeable)
24 sjme_errorCode error;
25 sjme_rom_library inLibrary;
27 if (closeable == NULL)
28 return SJME_ERROR_NULL_ARGUMENTS;
30 /* Recover library. */
31 inLibrary = (sjme_rom_library)closeable;
33 /* Delete the prefix if there is one. */
34 if (inLibrary->prefix != NULL)
36 /* Free it. */
37 if (sjme_error_is(error = sjme_alloc_free(
38 (sjme_pointer)inLibrary->prefix)))
39 return sjme_error_default(error);
41 /* Clear. */
42 inLibrary->prefix = NULL;
45 /* Delete name if there is one. */
46 if (inLibrary->name != NULL)
48 /* Free it. */
49 if (sjme_error_is(error = sjme_alloc_free(
50 (sjme_pointer)inLibrary->name)))
51 return sjme_error_default(error);
53 /* Clear. */
54 inLibrary->name = NULL;
57 /* Forward close handler. */
58 if (inLibrary->functions->close != NULL)
59 return inLibrary->functions->close(inLibrary);
61 /* Success! */
62 return SJME_ERROR_NONE;
65 sjme_errorCode sjme_rom_libraryHash(
66 sjme_attrInNotNull sjme_rom_library library,
67 sjme_attrOutNotNull sjme_jint* outHash)
69 if (library == NULL || outHash == NULL)
70 return SJME_ERROR_NULL_ARGUMENTS;
72 /* Does it need to be calculated? */
73 if (library->nameHash == 0)
75 /* This should always be set. */
76 if (library->name == NULL)
77 return SJME_ERROR_ILLEGAL_STATE;
79 /* Calculate the hash. */
80 library->nameHash = sjme_string_hash(library->name);
83 /* Copy it in. */
84 *outHash = library->nameHash;
85 return SJME_ERROR_NONE;
88 sjme_errorCode sjme_rom_libraryNew(
89 sjme_attrInNotNull sjme_alloc_pool* pool,
90 sjme_attrOutNotNull sjme_rom_library* outLibrary,
91 sjme_attrInNotNull sjme_lpcstr libName,
92 sjme_attrInNullable sjme_pointer data,
93 sjme_attrInNotNull const sjme_rom_libraryFunctions* inFunctions,
94 sjme_attrInNullable const sjme_frontEnd* copyFrontEnd)
96 sjme_errorCode error;
97 sjme_rom_library result;
99 if (pool == NULL || outLibrary == NULL || inFunctions == NULL ||
100 libName == NULL)
101 return SJME_ERROR_NULL_ARGUMENTS;
103 /* Required. */
104 if (inFunctions->init == NULL ||
105 inFunctions->close == NULL)
106 return SJME_ERROR_NOT_IMPLEMENTED;
108 /* Allocate result. */
109 result = NULL;
110 if (sjme_error_is(error = sjme_alloc_weakNew(pool,
111 sizeof(*result), sjme_nvm_enqueueHandler, NULL,
112 (void**)&result, NULL)) || result == NULL)
113 goto fail_alloc;
115 /* Setup result. */
116 result->common.closeable.closeHandler = sjme_rom_libraryClose;
117 result->common.type = SJME_NVM_STRUCTTYPE_ROM_LIBRARY;
118 result->cache.common.allocPool = pool;
119 result->functions = inFunctions;
121 /* Copy front end? */
122 if (copyFrontEnd != NULL)
123 memmove(&result->common.frontEnd, copyFrontEnd,
124 sizeof(*copyFrontEnd));
126 /* Call initializer. */
127 if (sjme_error_is(error = inFunctions->init(result, data)))
128 goto fail_init;
130 /* Set library name. */
131 result->name = NULL;
132 if (sjme_error_is(error = sjme_alloc_strdup(pool,
133 (sjme_lpstr*)&result->name, libName)))
134 goto fail_strdup;
136 /* Success! */
137 *outLibrary = result;
138 return SJME_ERROR_NONE;
140 fail_refUp:
141 fail_strdup:
142 fail_init:
143 fail_alloc:
144 if (result != NULL)
145 sjme_alloc_free(result);
147 return sjme_error_default(error);
150 sjme_errorCode sjme_rom_libraryRawRead(
151 sjme_attrInNotNull sjme_rom_library library,
152 sjme_attrOutNotNullBuf(length) sjme_pointer destPtr,
153 sjme_attrInPositive sjme_jint srcPos,
154 sjme_attrInPositive sjme_jint length)
156 /* This is just an alias for the other. */
157 return sjme_rom_libraryRawReadIter(
158 library, destPtr, 0, srcPos, 0, length);
161 sjme_errorCode sjme_rom_libraryRawReadIter(
162 sjme_attrInNotNull sjme_rom_library library,
163 sjme_attrOutNotNullBuf(length) sjme_pointer destPtr,
164 sjme_attrInPositive sjme_jint destOffset,
165 sjme_attrInPositive sjme_jint srcPos,
166 sjme_attrInPositive sjme_jint srcOffset,
167 sjme_attrInPositive sjme_jint length)
169 uintptr_t rawDestPtr;
170 sjme_errorCode error;
171 sjme_jint libSize;
173 if (library == NULL || destPtr == NULL)
174 return SJME_ERROR_NULL_ARGUMENTS;
176 /* Do we already know this will not work? */
177 if (library->cache.checkedRawAccess &&
178 !library->cache.validRawAccess)
179 return SJME_ERROR_UNSUPPORTED_OPERATION;
181 /* Check all the bounds variants possible, for overflow as well. */
182 rawDestPtr = (uintptr_t)destPtr;
183 if (destOffset < 0 || srcPos < 0 || srcOffset < 0 || length < 0 ||
184 (destOffset + length) < 0 || (srcPos + length) < 0 ||
185 (srcOffset + length) < 0 || (srcPos + srcOffset + length) < 0 ||
186 (rawDestPtr + destOffset) < rawDestPtr ||
187 (rawDestPtr + length) < rawDestPtr ||
188 (rawDestPtr + destOffset + length) < rawDestPtr)
189 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
191 /* Get the raw size of the target library. */
192 libSize = -2;
193 if (sjme_error_is(error = sjme_rom_libraryRawSize(library,
194 &libSize)) || libSize < 0)
196 if (libSize == -1)
197 return sjme_error_defaultOr(error,
198 SJME_ERROR_UNSUPPORTED_OPERATION);
199 return sjme_error_default(error);
202 /* Check bounds of the size to ensure it is correct. */
203 if (length > libSize || (srcPos + length) > libSize ||
204 (srcPos + srcOffset) > libSize ||
205 (srcPos + srcOffset + length) > libSize)
206 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
208 /* Check native library handler. */
209 if (library->functions->rawData == NULL)
210 return SJME_ERROR_UNSUPPORTED_OPERATION;
212 /* Call native library handler, which takes simpler arguments. */
213 return library->functions->rawData(library,
214 (sjme_pointer)(((uintptr_t)destPtr) + destOffset),
215 srcPos + srcOffset, length);
218 sjme_errorCode sjme_rom_libraryRawSize(
219 sjme_attrInNotNull sjme_rom_library library,
220 sjme_attrOutNotNull sjme_jint* outSize)
222 sjme_jint result;
223 sjme_errorCode error;
225 if (library == NULL || outSize == NULL)
226 return SJME_ERROR_NULL_ARGUMENTS;
228 /* Do we already know this will not work? */
229 if (library->cache.checkedRawAccess &&
230 !library->cache.validRawAccess)
231 return SJME_ERROR_UNSUPPORTED_OPERATION;
233 /* Size was already determined? */
234 if (library->cache.size > 0)
235 return library->cache.size;
237 /* Native handler must be valid! */
238 if (library->functions->rawSize == NULL)
239 goto fail_unsupported;
241 /* Call native handler. */
242 result = -2;
243 if (sjme_error_is(error = library->functions->rawSize(
244 library, &result)) || result < 0)
246 if (result == -1)
247 goto fail_unsupported;
248 return sjme_error_default(error);
251 /* Return result. */
252 *outSize = result;
253 return SJME_ERROR_NONE;
255 fail_unsupported:
256 /* Cache whether this is supported, so we need not bother? */
257 if (!library->cache.checkedRawAccess)
259 library->cache.checkedRawAccess = SJME_JNI_TRUE;
260 library->cache.validRawAccess = SJME_JNI_FALSE;
263 /* Not supported! */
264 return SJME_ERROR_UNSUPPORTED_OPERATION;
267 sjme_errorCode sjme_rom_libraryResourceAsStream(
268 sjme_attrInNotNull sjme_rom_library library,
269 sjme_attrOutNotNull sjme_stream_input* outStream,
270 sjme_attrInNotNull sjme_lpcstr rcName)
272 sjme_rom_libraryResourceStreamFunc resourceFunc;
273 sjme_stream_input result;
274 sjme_errorCode error;
276 if (library == NULL || outStream == NULL || rcName == NULL)
277 return SJME_ERROR_NULL_ARGUMENTS;
279 /* These must be set. */
280 if (library->functions == NULL ||
281 library->functions->resourceStream == NULL)
282 return SJME_ERROR_NOT_IMPLEMENTED;
284 /* Lock library. */
285 if (sjme_error_is(error = sjme_thread_spinLockGrab(
286 &library->common.lock)))
287 return sjme_error_default(error);
289 /* Get the resource function. */
290 resourceFunc = library->functions->resourceStream;
292 /* Ask for the resource. */
293 /* Remember to remove any starting slash, because internally everything */
294 /* is treated as absolute. */
295 result = NULL;
296 if (sjme_error_is(error = resourceFunc(library,
297 &result,
298 (rcName[0] == '/' ? rcName + 1 : rcName))) ||
299 result == NULL)
300 goto fail_locateResource;
302 /* Unlock library. */
303 if (sjme_error_is(error = sjme_thread_spinLockRelease(
304 &library->common.lock, NULL)))
305 return sjme_error_default(error);
307 /* Success! */
308 *outStream = result;
309 return SJME_ERROR_NONE;
311 /* Unlock library. */
312 fail_locateResource:
313 sjme_thread_spinLockRelease(&library->common.lock, NULL);
315 return sjme_error_default(error);