1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
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 // -------------------------------------------------------------------------*/
13 #include "sjme/nvm/rom.h"
14 #include "sjme/alloc.h"
15 #include "sjme/debug.h"
16 #include "sjme/nvm/payload.h"
17 #include "sjme/nvm/romInternal.h"
18 #include "sjme/util.h"
20 #include "sjme/cleanup.h"
23 * Initialization data for Zip libraries.
27 typedef struct sjme_rom_zipLibraryInitData
29 /** The Zip to access. */
32 /** The prefix for entry access. */
34 } sjme_rom_zipLibraryInitData
;
36 static sjme_errorCode
sjme_rom_zipLibraryClose(
37 sjme_attrInNotNull sjme_rom_library inLibrary
)
42 if (inLibrary
== NULL
)
43 return SJME_ERROR_NULL_ARGUMENTS
;
45 /* Recover zip, ignore if already closed. */
46 zip
= inLibrary
->handle
;
48 return SJME_ERROR_NONE
;
51 if (sjme_error_is(error
= sjme_closeable_close(
52 SJME_AS_CLOSEABLE(zip
))))
53 return sjme_error_default(error
);
55 /* Remove reference to it. */
56 inLibrary
->handle
= NULL
;
59 return SJME_ERROR_NONE
;
62 static sjme_errorCode
sjme_rom_zipLibraryInit(
63 sjme_attrInNotNull sjme_rom_library inLibrary
,
64 sjme_attrInNullable sjme_pointer data
)
67 sjme_rom_zipLibraryInitData
* init
;
70 if (inLibrary
== NULL
|| init
== NULL
)
71 return SJME_ERROR_NULL_ARGUMENTS
;
73 /* Remember handle to the Zip for accessing later. */
74 inLibrary
->handle
= init
->zip
;
76 /* Setup prefix, if there is one. */
77 if (init
->prefix
!= NULL
)
78 if (sjme_error_is(error
= sjme_alloc_strdup(
79 inLibrary
->cache
.common
.allocPool
,
80 (sjme_lpstr
*)&inLibrary
->prefix
, init
->prefix
)))
81 return sjme_error_default(error
);
84 return SJME_ERROR_NONE
;
87 static sjme_errorCode
sjme_rom_zipLibraryResourceStream(
88 sjme_attrInNotNull sjme_rom_library inLibrary
,
89 sjme_attrOutNotNull sjme_stream_input
* outStream
,
90 sjme_attrInNotNull sjme_lpcstr resourceName
)
95 sjme_cchar actualName
[SJME_MAX_PATH
];
97 if (inLibrary
== NULL
|| outStream
== NULL
|| resourceName
== NULL
)
98 return SJME_ERROR_NULL_ARGUMENTS
;
101 zip
= inLibrary
->handle
;
103 return SJME_ERROR_ILLEGAL_STATE
;
105 /* Determine the actual name of the entry. */
106 memset(actualName
, 0, sizeof(actualName
));
107 if (inLibrary
->prefix
!= NULL
)
108 snprintf(actualName
, SJME_MAX_PATH
- 1, "%s/%s",
109 inLibrary
->prefix
, resourceName
);
111 snprintf(actualName
, SJME_MAX_PATH
- 1, "%s/%s",
112 inLibrary
->prefix
, resourceName
);
114 /* Locate the entry. */
115 memset(&entry
, 0, sizeof(entry
));
116 if (sjme_error_is(error
= sjme_zip_locateEntry(zip
,
117 &entry
, actualName
)))
119 /* File not found maps to resource not found. */
120 if (error
== SJME_ERROR_FILE_NOT_FOUND
)
121 return SJME_ERROR_RESOURCE_NOT_FOUND
;
123 return sjme_error_default(error
);
126 /* Open input stream over resource. */
127 return sjme_zip_entryRead(&entry
, outStream
);
130 /** Library functions for Zip access. */
131 static const sjme_rom_libraryFunctions sjme_rom_zipLibraryFunctions
=
133 .close
= sjme_rom_zipLibraryClose
,
134 .init
= sjme_rom_zipLibraryInit
,
135 .resourceStream
= sjme_rom_zipLibraryResourceStream
,
138 sjme_errorCode
sjme_rom_libraryFromZip(
139 sjme_attrInNotNull sjme_alloc_pool
* pool
,
140 sjme_attrOutNotNull sjme_rom_library
* outLibrary
,
141 sjme_attrInNotNull sjme_lpcstr libName
,
142 sjme_attrInNullable sjme_lpcstr prefix
,
143 sjme_attrInNotNull sjme_zip zip
)
145 sjme_errorCode error
;
146 sjme_rom_library result
;
147 sjme_rom_zipLibraryInitData init
;
149 if (pool
== NULL
|| outLibrary
== NULL
|| zip
== NULL
)
150 return SJME_ERROR_NULL_ARGUMENTS
;
152 /* Setup initialization data. */
153 memset(&init
, 0, sizeof(init
));
155 init
.prefix
= prefix
;
157 /* Setup new library. */
159 if (sjme_error_is(error
= sjme_rom_libraryNew(pool
,
160 &result
, libName
, &init
,
161 &sjme_rom_zipLibraryFunctions
, NULL
)) ||
163 goto fail_libraryNew
;
165 /* Count up Zip, since we are using it now. */
166 if (sjme_error_is(error
= sjme_alloc_weakRef(zip
, NULL
)))
170 *outLibrary
= result
;
171 return SJME_ERROR_NONE
;
175 return sjme_error_default(error
);
178 sjme_errorCode
sjme_rom_libraryFromZipMemory(
179 sjme_attrInNotNull sjme_alloc_pool
* pool
,
180 sjme_attrOutNotNull sjme_rom_library
* outLibrary
,
181 sjme_attrInNotNull sjme_lpcstr libName
,
182 sjme_attrInNotNull sjme_cpointer base
,
183 sjme_attrInPositive sjme_jint length
)
185 sjme_seekable seekable
;
186 sjme_errorCode error
;
188 if (pool
== NULL
|| outLibrary
== NULL
|| base
== NULL
)
189 return SJME_ERROR_NULL_ARGUMENTS
;
192 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
194 /* Get source seekable. */
196 if (sjme_error_is(error
= sjme_seekable_openMemory(pool
,
197 &seekable
, (sjme_pointer
)base
, length
)) ||
199 return sjme_error_default(error
);
201 /* This is just an alias for the other function. */
202 return sjme_rom_libraryFromZipSeekable(pool
, outLibrary
,
206 sjme_errorCode
sjme_rom_libraryFromZipSeekable(
207 sjme_attrInNotNull sjme_alloc_pool
* pool
,
208 sjme_attrOutNotNull sjme_rom_library
* outLibrary
,
209 sjme_attrInNotNull sjme_lpcstr libName
,
210 sjme_attrInNotNull sjme_seekable seekable
)
212 sjme_errorCode error
;
215 if (pool
== NULL
|| outLibrary
== NULL
|| seekable
== NULL
)
216 return SJME_ERROR_NULL_ARGUMENTS
;
218 /* Try opening as a Zip file. */
220 if (sjme_error_is(error
= sjme_zip_openSeekable(pool
, &zip
,
221 seekable
)) || zip
== NULL
)
222 return sjme_error_default(error
);
224 /* Forward Zip loading. */
225 return sjme_rom_libraryFromZip(pool
, outLibrary
, libName
,