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 // -------------------------------------------------------------------------*/
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
;
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
)
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
;
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
));
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
);
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
;
120 if (sjme_error_is(error
= sjme_thread_spinLockGrab(
122 return sjme_error_default(error
);
125 error
= seekable
->functions
->read(seekable
,
126 &seekable
->implState
, outBuf
, seekBase
, length
);
129 if (sjme_error_is(sjme_thread_spinLockRelease(&seekable
->lock
,
131 return sjme_error_default(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
;
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
);
166 return SJME_ERROR_OUT_OF_MEMORY
;
167 memset(tempBuf
, 0, length
);
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
)
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
;
227 if (seekable
== NULL
|| outSize
== NULL
)
228 return SJME_ERROR_NULL_ARGUMENTS
;
230 if (seekable
->functions
->size
== NULL
)
231 return SJME_ERROR_NOT_IMPLEMENTED
;
234 if (sjme_error_is(error
= sjme_thread_spinLockGrab(
236 return sjme_error_default(error
);
238 /* Forward size call. */
240 error
= seekable
->functions
->size(seekable
,
241 &seekable
->implState
, &size
);
244 if (sjme_error_is(sjme_thread_spinLockRelease(&seekable
->lock
,
246 return sjme_error_default(error
);
249 if (sjme_error_is(error
) || size
< 0)
250 return sjme_error_default(error
);
254 return SJME_ERROR_NONE
;