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 // -------------------------------------------------------------------------*/
16 #ifndef SQUIRRELJME_SEEKABLE_H
17 #define SQUIRRELJME_SEEKABLE_H
19 #include "sjme/stdTypes.h"
20 #include "sjme/alloc.h"
21 #include "sjme/closeable.h"
25 #ifndef SJME_CXX_IS_EXTERNED
26 #define SJME_CXX_IS_EXTERNED
27 #define SJME_CXX_SQUIRRELJME_SEEKABLE_H
29 #endif /* #ifdef SJME_CXX_IS_EXTERNED */
30 #endif /* #ifdef __cplusplus */
32 /*--------------------------------------------------------------------------*/
35 * Core seekable structure.
39 typedef struct sjme_seekableBase sjme_seekableBase
;
42 * Opaque seekable data.
46 typedef sjme_seekableBase
* sjme_seekable
;
49 * Seekable lock core structure.
53 typedef struct sjme_seekable_lockBase sjme_seekable_lockBase
;
56 * Opaque locked seekable structure.
60 typedef struct sjme_seekable_lockBase
* sjme_seekable_lock
;
62 struct sjme_seekable_lockBase
64 /** The owning seekable. */
65 sjme_seekable seekable
;
68 * The base address pointer.
70 * Depending on the implementation, if the memory within the lock is
71 * modified it may directly change the resultant memory or file.
75 /** The length of the lock. */
80 * This is the action that can change what happens when a locked region is
85 typedef enum sjme_seekable_unlockAction
87 /** Discard any bytes that were written. */
88 SJME_SEEKABLE_UNLOCK_ACTION_DISCARD
,
91 * Write the data back to the seekable.
93 * Note that this only has an effect if the buffer in memory is a copy
94 * of the source seekable, in which case it was not directly mappable.
96 SJME_SEEKABLE_UNLOCK_ACTION_WRITE_BACK
,
98 /** The number of unlock actions. */
99 SJME_NUM_SEEKABLE_UNLOCK_ACTION
100 } sjme_seekable_unlockAction
;
103 * Implementation state within seekables.
107 typedef struct sjme_seekable_implState
109 /** The pool this is in. */
110 sjme_alloc_pool
* inPool
;
112 /** Internal handle. */
115 /** Internal index. */
118 /** Internal length. */
121 /** Forward close? */
122 sjme_jboolean forwardClose
;
123 } sjme_seekable_implState
;
126 * Closes the seekable stream.
128 * @param inSeekable The current seekable.
129 * @param inImplState The implementation state.
130 * @return Any resultant error, if any.
133 typedef sjme_errorCode (*sjme_seekable_closeFunc
)(
134 sjme_attrInNotNull sjme_seekable inSeekable
,
135 sjme_attrInNotNull sjme_seekable_implState
* inImplState
);
138 * Initializes the new seekable.
140 * @param inSeekable The current seekable.
141 * @param inImplState The implementation state.
142 * @param data Any passed in data through initialize.
143 * @return Any resultant error, if any.
146 typedef sjme_errorCode (*sjme_seekable_initFunc
)(
147 sjme_attrInNotNull sjme_seekable inSeekable
,
148 sjme_attrInNotNull sjme_seekable_implState
* inImplState
,
149 sjme_attrInNullable sjme_pointer data
);
152 * Reads from the given seekable.
154 * @param inSeekable The current seekable.
155 * @param inImplState The implementation state.
156 * @param outBuf The buffer to write to.
157 * @param base The base address to read from.
158 * @param length The number of bytes to read.
159 * @return Any resultant error, if any.
162 typedef sjme_errorCode (*sjme_seekable_readFunc
)(
163 sjme_attrInNotNull sjme_seekable inSeekable
,
164 sjme_attrInNotNull sjme_seekable_implState
* inImplState
,
165 sjme_attrOutNotNullBuf(length
) sjme_buffer outBuf
,
166 sjme_attrInPositive sjme_jint base
,
167 sjme_attrInPositiveNonZero sjme_jint length
);
170 * Returns the size of the seekable.
172 * @param inSeekable The current seekable.
173 * @param inImplState The implementation state.
174 * @param outSize The resultant size of the seekable.
175 * @return Any resultant error, if any.
178 typedef sjme_errorCode (*sjme_seekable_sizeFunc
)(
179 sjme_attrInNotNull sjme_seekable inSeekable
,
180 sjme_attrInNotNull sjme_seekable_implState
* inImplState
,
181 sjme_attrOutNotNull sjme_jint
* outSize
);
184 * Functions for seekable implementations.
188 typedef struct sjme_seekable_functions
190 /** Closes the stream. */
191 sjme_seekable_closeFunc close
;
193 /** Initializes the stream. */
194 sjme_seekable_initFunc init
;
196 /** Read from the given stream. */
197 sjme_seekable_readFunc read
;
199 /** Return the size of the stream. */
200 sjme_seekable_sizeFunc size
;
201 } sjme_seekable_functions
;
203 struct sjme_seekableBase
206 sjme_closeableBase closable
;
208 /** Implementation state. */
209 sjme_seekable_implState implState
;
211 /** Front end data. */
212 sjme_frontEnd frontEnd
;
214 /** Functions for stream access. */
215 const sjme_seekable_functions
* functions
;
217 /** Spinlock for stream access. */
218 sjme_thread_spinLock lock
;
220 /** The pool this is in. */
221 sjme_alloc_pool
* inPool
;
225 * Opens a generic stream.
227 * @param inPool The pool to allocate within.
228 * @param outSeekable The resultant seekable.
229 * @param inFunctions The seekable functions.
230 * @param data Any data to pass to the initialize function.
231 * @param copyFrontEnd Front-end data as needed.
232 * @return Any resultant error, if any,
235 sjme_errorCode
sjme_seekable_open(
236 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
237 sjme_attrOutNotNull sjme_seekable
* outSeekable
,
238 sjme_attrInNotNull
const sjme_seekable_functions
* inFunctions
,
239 sjme_attrInNullable sjme_pointer data
,
240 sjme_attrInNullable
const sjme_frontEnd
* copyFrontEnd
);
243 * Initializes a seekable from the given memory range.
245 * @param inPool The pool to allocate within.
246 * @param outSeekable The resultant seekable.
247 * @param base The base memory address.
248 * @param length The length of memory block.
249 * @return Any resultant error, if any.
252 sjme_errorCode
sjme_seekable_openMemory(
253 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
254 sjme_attrOutNotNull sjme_seekable
* outSeekable
,
255 sjme_attrInNotNull sjme_pointer base
,
256 sjme_attrInPositive sjme_jint length
);
259 * Wraps a seekable and provides a sub-seekable within this.
261 * @param inPool The pool to allocate within.
262 * @param inSeekable The input seekable, to get the sub-seekable of.
263 * @param outSeekable The output seekable.
264 * @param base The base address to get.
265 * @param length The length of the seekable range.
266 * @return Any resultant error, if any.
269 sjme_errorCode
sjme_seekable_openSeekable(
270 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
271 sjme_attrInNotNull sjme_seekable inSeekable
,
272 sjme_attrOutNotNull sjme_seekable
* outSeekable
,
273 sjme_attrInPositive sjme_jint base
,
274 sjme_attrInPositive sjme_jint length
);
277 * Reads from the given seekable.
279 * @param seekable The seekable to read from.
280 * @param outBuf The output buffer.
281 * @param seekBase The base of the seekable to read from.
282 * @param length The number of bytes to read.
283 * @return Any resultant error, if any.
286 sjme_errorCode
sjme_seekable_read(
287 sjme_attrInNotNull sjme_seekable seekable
,
288 sjme_attrOutNotNull sjme_buffer outBuf
,
289 sjme_attrInPositive sjme_jint seekBase
,
290 sjme_attrInPositive sjme_jint length
);
293 * Reads from the given seekable in reverse byte order for every @c wordSize
294 * that is read from the input.
296 * @param seekable The seekable to read from.
297 * @param wordSize The word size for the read, every number of this many
298 * bytes will be reversed.
299 * @param outBuf The output buffer.
300 * @param seekBase The base of the seekable to read from.
301 * @param length The number of bytes to read.
302 * @return Any resultant error, if any.
305 sjme_errorCode
sjme_seekable_readReverse(
306 sjme_attrInNotNull sjme_seekable seekable
,
307 sjme_attrInRange(2, 8) sjme_jint wordSize
,
308 sjme_attrOutNotNull sjme_buffer outBuf
,
309 sjme_attrInPositive sjme_jint seekBase
,
310 sjme_attrInPositive sjme_jint length
);
312 #if defined(SJME_CONFIG_HAS_LITTLE_ENDIAN)
315 * Reads big endian data from the given seekable.
317 * @param seekable The seekable to read from.
318 * @param wordSize The word size for the read, every number of bytes will
319 * be possibly reversed if required.
320 * @param outBuf The output buffer.
321 * @param seekBase The base of the seekable to read from.
322 * @param length The number of bytes to read.
323 * @return Any resultant error, if any.
326 #define sjme_seekable_readBig(seekable, wordSize, outBuf, seekBase, \
328 (sjme_seekable_readReverse((seekable), (wordSize), (outBuf), (seekBase), \
332 * Reads little endian data from the given seekable.
334 * @param seekable The seekable to read from.
335 * @param wordSize The word size for the read, every number of bytes will
336 * be possibly reversed if required.
337 * @param outBuf The output buffer.
338 * @param seekBase The base of the seekable to read from.
339 * @param length The number of bytes to read.
340 * @return Any resultant error, if any.
343 #define sjme_seekable_readLittle(seekable, wordSize, outBuf, seekBase, \
345 (sjme_seekable_read((seekable), (outBuf), (seekBase), (length)))
350 * Reads big endian data from the given seekable.
352 * @param seekable The seekable to read from.
353 * @param wordSize The word size for the read, every number of bytes will
354 * be possibly reversed if required.
355 * @param outBuf The output buffer.
356 * @param seekBase The base of the seekable to read from.
357 * @param length The number of bytes to read.
358 * @return Any resultant error, if any.
361 #define sjme_seekable_readBig(seekable, wordSize, outBuf, seekBase, \
363 (sjme_seekable_read((seekable), (outBuf), (seekBase), (length)))
366 * Reads little endian data from the given seekable.
368 * @param seekable The seekable to read from.
369 * @param wordSize The word size for the read, every number of bytes will
370 * be possibly reversed if required.
371 * @param outBuf The output buffer.
372 * @param seekBase The base of the seekable to read from.
373 * @param length The number of bytes to read.
374 * @return Any resultant error, if any.
377 #define sjme_seekable_readLittle(seekable, wordSize, outBuf, seekBase, \
379 (sjme_seekable_readReverse((seekable), (wordSize), (outBuf), (seekBase), \
385 * Locks a region of a seekable so that the data stored there can be accessed
386 * directly via memory access. Depending on the seekable implementation, there
387 * are multiple possibilities as to what may occur: if the seekable is
388 * directly from memory it will just map to that pointer accordingly, if
389 * the seekable is backed by a file then it will be memory mapped, otherwise
390 * a buffer will be created with a copy of the bytes at the given region and
391 * will stay as such until unlocked. Per the implementation, if the seekable
392 * data is modified in memory it may change that actual memory or file.
394 * @param seekable The seekable to lock within.
395 * @param outLock The resultant lock.
396 * @param base The base address within the seekable to lock.
397 * @param length The number of bytes to lock.
398 * @return Any resultant error, if any.
401 sjme_errorCode
sjme_seekable_regionLock(
402 sjme_attrInNotNull sjme_seekable seekable
,
403 sjme_attrOutNotNull sjme_seekable_lock
* outLock
,
404 sjme_attrInPositive sjme_jint base
,
405 sjme_attrInPositive sjme_jint length
);
408 * Unlocks a locked seekable region, the resultant action may or may not
409 * have an effect depending on the implementation.
411 * @param inLock The lock to unlock.
412 * @param action The action to perform on the unlock.
413 * @return Any resultant error, if any.
414 * @see sjme_seekable_unlockAction
417 sjme_errorCode
sjme_seekable_regionUnlock(
418 sjme_attrInNotNull sjme_seekable_lock inLock
,
419 sjme_attrInRange(0, SJME_NUM_SEEKABLE_UNLOCK_ACTION
)
420 sjme_seekable_unlockAction action
);
423 * Returns the size of the given seekable.
425 * @param seekable The seekable to get the size of.
426 * @param outSize The size of the seekable.
427 * @return Any resultant error, if any.
430 sjme_errorCode
sjme_seekable_size(
431 sjme_attrInNotNull sjme_seekable seekable
,
432 sjme_attrOutNotNull sjme_jint
* outSize
);
434 /*--------------------------------------------------------------------------*/
438 #ifdef SJME_CXX_SQUIRRELJME_SEEKABLE_H
440 #undef SJME_CXX_SQUIRRELJME_SEEKABLE_H
441 #undef SJME_CXX_IS_EXTERNED
442 #endif /* #ifdef SJME_CXX_SQUIRRELJME_SEEKABLE_H */
443 #endif /* #ifdef __cplusplus */
445 #endif /* SQUIRRELJME_SEEKABLE_H */