Base for method reading.
[SquirrelJME.git] / nanocoat / src / rom.c
blob4c9875d5842063a904ec4b3a4365bdc00e66ddfc
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 sjme_errorCode sjme_rom_resolveClassPathById(
22 sjme_attrInNotNull sjme_rom_suite inSuite,
23 sjme_attrInNotNull const sjme_list_sjme_jint* inIds,
24 sjme_attrOutNotNull sjme_list_sjme_rom_library** outLibs)
26 sjme_list_sjme_rom_library* suiteLibs;
27 sjme_errorCode error;
28 sjme_jint length, i, numLibs, at, libId;
29 sjme_rom_library* working;
30 sjme_rom_library checkLibrary;
32 if (inSuite == NULL || inIds == NULL || outLibs == NULL)
33 return SJME_ERROR_NULL_ARGUMENTS;
35 /* Debug. */
36 sjme_message("sjme_rom_resolveClassPathById(%p, %p, %p)",
37 inSuite, inIds, outLibs);
39 /* How many are we looking for? */
40 length = inIds->length;
41 if (length < 0)
42 return SJME_ERROR_INVALID_ARGUMENT;
44 /* Debug. */
45 sjme_message("Looking for %d libraries...", length);
47 /* Allocate temporary storage on the stack for the libraries we want. */
48 working = sjme_alloca(sizeof(*working) * length);
49 if (working == NULL)
50 return sjme_error_outOfMemory(NULL, length);
52 /* Make sure it is cleared. */
53 memset(working, 0, sizeof(*working) * length);
55 /* Debug. */
56 sjme_message("Getting library list...");
58 /* Obtain the list of libraries within the suite. */
59 suiteLibs = NULL;
60 if (sjme_error_is(error = sjme_rom_suiteLibraries(inSuite,
61 &suiteLibs)) || suiteLibs == NULL)
62 return sjme_error_default(error);
64 /* Debug. */
65 sjme_message("Done: %p!", suiteLibs);
66 sjme_message("Found %d libraries.", suiteLibs->length);
68 /* Go through and find the ones with matching IDs. */
69 /* Order by library because there is likely to be more of those. */
70 numLibs = suiteLibs->length;
71 for (i = 0; i < numLibs; i++)
73 /* Which library is this? */
74 checkLibrary = suiteLibs->elements[i];
76 #if defined(SJME_CONFIG_DEBUG)
77 /* Debug. */
78 sjme_message("Looking at library #%d: %p",
79 i, checkLibrary);
80 #endif
82 /* Need to initialize the ID? */
83 libId = checkLibrary->id;
84 if (libId == 0)
86 /* No function? */
87 if (inSuite->functions->libraryId == NULL)
88 return SJME_ERROR_ILLEGAL_STATE;
90 /* Get the library ID. */
91 if (sjme_error_is(error = inSuite->functions->libraryId(
92 inSuite, checkLibrary,
93 &libId)))
94 return sjme_error_default(error);
96 /* Library ID function did not store it? */
97 if (checkLibrary->id == 0)
98 checkLibrary->id = libId;
101 /* Scan through the requested classpath for matches. */
102 for (at = 0; at < length; at++)
103 if (inIds->elements[at] == libId)
105 working[at] = checkLibrary;
106 break;
110 /* Scan through and fail if any are null, that is not found. */
111 for (at = 0; at < length; at++)
112 if (working[at] == NULL)
113 return SJME_ERROR_LIBRARY_NOT_FOUND;
115 /* Return the libraries which gets placed into a list as a copy. */
116 return sjme_list_newA(inSuite->cache.common.allocPool,
117 sjme_rom_library, 0, length, outLibs, working);
120 sjme_errorCode sjme_rom_resolveClassPathByName(
121 sjme_attrInNotNull sjme_rom_suite inSuite,
122 sjme_attrInNotNull const sjme_list_sjme_lpcstr* inNames,
123 sjme_attrOutNotNull sjme_list_sjme_rom_library** outLibs)
125 sjme_list_sjme_rom_library* suiteLibs;
126 sjme_errorCode error;
127 sjme_jint length, i, at, hash, numSuiteLibs;
128 sjme_rom_library* working;
129 sjme_rom_library lib;
130 sjme_jint* inHashes;
132 if (inSuite == NULL || inNames == NULL || outLibs == NULL)
133 return SJME_ERROR_NULL_ARGUMENTS;
135 /* How many are we looking for? */
136 length = inNames->length;
137 if (length < 0)
138 return SJME_ERROR_INVALID_ARGUMENT;
140 /* Make sure there are no NULL libraries as input. */
141 for (i = 0; i < length; i++)
142 if (inNames->elements[i] == NULL)
143 return SJME_ERROR_NULL_ARGUMENTS;
145 /* Allocate temporary storage on the stack for the libraries we want. */
146 working = sjme_alloca(sizeof(*working) * length);
147 inHashes = sjme_alloca(sizeof(*inHashes) * length);
148 if (working == NULL || inHashes == NULL)
149 return sjme_error_outOfMemory(NULL, length);
151 /* Clear memory. */
152 memset(working, 0, sizeof(*working) * length);
153 memset(inHashes, 0, sizeof(*inHashes) * length);
155 /* First hash all the input libraries, so we can quickly scan through. */
156 for (i = 0; i < length; i++)
157 inHashes[i] = sjme_string_hash(inNames->elements[i]);
159 /* Obtain the list of libraries within the suite. */
160 suiteLibs = NULL;
161 if (sjme_error_is(error = sjme_rom_suiteLibraries(inSuite,
162 &suiteLibs) || suiteLibs == NULL))
163 return sjme_error_default(error);
165 /* Go through each library and get hash matches. */
166 numSuiteLibs = suiteLibs->length;
167 for (i = 0; i < numSuiteLibs; i++)
169 /* Get hash of this library. */
170 lib = suiteLibs->elements[i];
171 if (sjme_error_is(error = sjme_rom_libraryHash(lib,
172 &hash)))
173 return sjme_error_default(error);
175 /* Look for match in output. */
176 for (at = 0; at < length; at++)
177 if (working[at] == NULL && inHashes[at] == hash &&
178 0 == strcmp(inNames->elements[at], lib->name))
179 working[at] = lib;
182 /* Scan through and fail if any are null, that is not found. */
183 for (at = 0; at < length; at++)
184 if (working[at] == NULL)
185 return SJME_ERROR_LIBRARY_NOT_FOUND;
187 /* Return the libraries which gets placed into a list as a copy. */
188 return sjme_list_newA(inSuite->cache.common.allocPool,
189 sjme_rom_library, 0, length, outLibs, working);