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/nvm/classy.h"
13 #include "sjme/debug.h"
14 #include "sjme/cleanup.h"
16 /** The magic number for classes. */
17 #define SJME_CLASS_MAGIC INT32_C(0xCAFEBABE)
19 /** CLDC 1.1 max version (JSR 30). */
20 #define SJME_CLASS_CLDC_1_0_MAX INT32_C(3080191)
22 /** CLDC 1.1 max version. (JSR 139). */
23 #define SJME_CLASS_CLDC_1_1_MAX INT32_C(3342335)
25 /** CLDC 8 max version. */
26 #define SJME_CLASS_CLDC_1_8_MAX INT32_C(3407872)
29 #define SJME_CLASS_ACC_PUBLIC INT16_C(0x0001)
32 #define SJME_CLASS_ACC_PRIVATE INT16_C(0x0002)
35 #define SJME_CLASS_ACC_PROTECTED INT16_C(0x0004)
38 #define SJME_CLASS_ACC_STATIC INT16_C(0x0008)
40 /** Final class or member. */
41 #define SJME_CLASS_ACC_FINAL INT16_C(0x0010)
43 /** Alternative @c invokesuper logic. */
44 #define SJME_CLASS_ACC_SUPER INT16_C(0x0020)
46 /** Synchronized method. */
47 #define SJME_CLASS_ACC_SYNCHRONIZED INT16_C(0x0020)
50 #define SJME_CLASS_ACC_BRIDGE INT16_C(0x0040)
52 /** Variable arguments. */
53 #define SJME_CLASS_ACC_VARARGS INT16_C(0x0080)
56 #define SJME_CLASS_ACC_NATIVE INT16_C(0x0100)
58 /** Class is an interface. */
59 #define SJME_CLASS_ACC_INTERFACE INT16_C(0x0200)
61 /** Abstract class or method. */
62 #define SJME_CLASS_ACC_ABSTRACT INT16_C(0x0400)
64 /** Strict floating point method. */
65 #define SJME_CLASS_ACC_STRICTFP INT16_C(0x0800)
67 /** Synthetic class or member. */
68 #define SJME_CLASS_ACC_SYNTHETIC INT16_C(0x1000)
70 /** Field is volatile. */
71 #define SJME_CLASS_ACC_VOLATILE INT16_C(0x0040)
73 /** Field is transient. */
74 #define SJME_CLASS_ACC_TRANSIENT INT16_C(0x0080)
76 /** Class is an annotation. */
77 #define SJME_CLASS_ACC_ANNOTATION INT16_C(0x2000)
79 /** Class is an enum. */
80 #define SJME_CLASS_ACC_ENUM INT16_C(0x4000)
82 static sjme_errorCode
sjme_class_readPoolRefIndex(
83 sjme_attrInNotNull sjme_stream_input inStream
,
84 sjme_attrInNotNull sjme_class_poolInfo inClassPool
,
85 sjme_attrInPositiveNonZero sjme_class_poolType desireType
,
86 sjme_attrInValue sjme_jboolean canNull
,
87 sjme_attrOutNotNull sjme_class_poolEntry
** outEntry
)
91 sjme_class_poolEntry
* result
;
93 if (inStream
== NULL
|| inClassPool
== NULL
|| outEntry
== NULL
)
94 return SJME_ERROR_NULL_ARGUMENTS
;
98 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
100 return sjme_error_default(error
);
102 /* Not a valid index? */
103 if (index
<= 0 || index
>= inClassPool
->pool
->length
)
105 /* Can be zero index for nothing, however. */
106 if (index
== 0 && canNull
)
109 return SJME_ERROR_NONE
;
112 return SJME_ERROR_INVALID_CLASS_POOL_INDEX
;
115 /* Must be the desired type. */
116 result
= &inClassPool
->pool
->elements
[index
];
117 if (result
->type
!= desireType
)
118 return SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
122 return SJME_ERROR_NONE
;
125 static const sjme_class_parseAttributeHandlerInfo sjme_class_classAttr
[] =
130 static sjme_errorCode
sjme_class_classFlagsParse(
131 sjme_attrInNotNull sjme_stream_input inStream
,
132 sjme_attrOutNotNull sjme_class_classFlags
* outFlags
)
134 sjme_errorCode error
;
135 sjme_jshort rawFlags
;
137 if (inStream
== NULL
|| outFlags
== NULL
)
138 return SJME_ERROR_NULL_ARGUMENTS
;
142 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
143 inStream
, &rawFlags
)) || rawFlags
< 0)
144 return sjme_error_default(error
);
146 /* Translate to bitfield. */
147 if ((rawFlags
& SJME_CLASS_ACC_PUBLIC
) != 0)
148 outFlags
->access
.public = SJME_JNI_TRUE
;
149 if ((rawFlags
& SJME_CLASS_ACC_FINAL
) != 0)
150 outFlags
->final
= SJME_JNI_TRUE
;
151 if ((rawFlags
& SJME_CLASS_ACC_SUPER
) != 0)
152 outFlags
->super
= SJME_JNI_TRUE
;
153 if ((rawFlags
& SJME_CLASS_ACC_INTERFACE
) != 0)
154 outFlags
->interface
= SJME_JNI_TRUE
;
155 if ((rawFlags
& SJME_CLASS_ACC_ABSTRACT
) != 0)
156 outFlags
->abstract
= SJME_JNI_TRUE
;
157 if ((rawFlags
& SJME_CLASS_ACC_SYNTHETIC
) != 0)
158 outFlags
->synthetic
= SJME_JNI_TRUE
;
159 if ((rawFlags
& SJME_CLASS_ACC_ANNOTATION
) != 0)
160 outFlags
->annotation
= SJME_JNI_TRUE
;
161 if ((rawFlags
& SJME_CLASS_ACC_ENUM
) != 0)
162 outFlags
->enumeration
= SJME_JNI_TRUE
;
164 /* Cannot be abstract and final. */
165 /* Annotation must be an interface. */
166 /* Interface must be abstract and not final, super, or enum */
167 if ((outFlags
->abstract
&& outFlags
->final
) ||
168 (outFlags
->annotation
&& !outFlags
->interface
) ||
169 (outFlags
->interface
&& (!outFlags
->abstract
||
170 outFlags
->final
|| outFlags
->super
|| outFlags
->enumeration
)))
171 return SJME_ERROR_INVALID_CLASS_FLAGS
;
174 return SJME_ERROR_NONE
;
177 static sjme_errorCode
sjme_class_codeAttrLineNumberTable(
178 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
179 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
180 sjme_attrInNotNull sjme_stringPool inStringPool
,
181 sjme_attrInNotNull sjme_pointer context
,
182 sjme_attrInNotNull sjme_lpcstr attrName
,
183 sjme_attrInNotNull sjme_stream_input attrStream
,
184 sjme_attrInNotNullBuf(attrLen
) sjme_pointer attrData
,
185 sjme_attrInPositive sjme_jint attrLen
)
187 if (inPool
== NULL
|| inConstPool
== NULL
|| inStringPool
== NULL
||
188 context
== NULL
|| attrName
== NULL
|| attrData
== NULL
||
190 return SJME_ERROR_NULL_ARGUMENTS
;
193 return SJME_ERROR_NOT_IMPLEMENTED
;
196 static sjme_errorCode
sjme_class_codeAttrStackMap(
197 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
198 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
199 sjme_attrInNotNull sjme_stringPool inStringPool
,
200 sjme_attrInNotNull sjme_pointer context
,
201 sjme_attrInNotNull sjme_lpcstr attrName
,
202 sjme_attrInNotNull sjme_stream_input attrStream
,
203 sjme_attrInNotNullBuf(attrLen
) sjme_pointer attrData
,
204 sjme_attrInPositive sjme_jint attrLen
)
206 if (inPool
== NULL
|| inConstPool
== NULL
|| inStringPool
== NULL
||
207 context
== NULL
|| attrName
== NULL
|| attrData
== NULL
||
209 return SJME_ERROR_NULL_ARGUMENTS
;
212 return SJME_ERROR_NOT_IMPLEMENTED
;
215 static sjme_errorCode
sjme_class_codeAttrStackMapTable(
216 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
217 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
218 sjme_attrInNotNull sjme_stringPool inStringPool
,
219 sjme_attrInNotNull sjme_pointer context
,
220 sjme_attrInNotNull sjme_lpcstr attrName
,
221 sjme_attrInNotNull sjme_stream_input attrStream
,
222 sjme_attrInNotNullBuf(attrLen
) sjme_pointer attrData
,
223 sjme_attrInPositive sjme_jint attrLen
)
225 if (inPool
== NULL
|| inConstPool
== NULL
|| inStringPool
== NULL
||
226 context
== NULL
|| attrName
== NULL
|| attrData
== NULL
||
228 return SJME_ERROR_NULL_ARGUMENTS
;
231 return SJME_ERROR_NOT_IMPLEMENTED
;
234 static const sjme_class_parseAttributeHandlerInfo sjme_class_codeAttr
[] =
238 sjme_class_codeAttrLineNumberTable
},
240 sjme_class_codeAttrStackMap
},
242 sjme_class_codeAttrStackMapTable
},
247 static sjme_errorCode
sjme_class_fieldAttrConstantValue(
248 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
249 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
250 sjme_attrInNotNull sjme_stringPool inStringPool
,
251 sjme_attrInNotNull sjme_pointer context
,
252 sjme_attrInNotNull sjme_lpcstr attrName
,
253 sjme_attrInNotNull sjme_stream_input attrStream
,
254 sjme_attrInNotNullBuf(attrLen
) sjme_pointer attrData
,
255 sjme_attrInPositive sjme_jint attrLen
)
257 sjme_errorCode error
;
258 sjme_class_fieldInfo fieldInfo
;
260 sjme_class_poolEntry
* item
;
263 if (inPool
== NULL
|| inConstPool
== NULL
|| inStringPool
== NULL
||
264 context
== NULL
|| attrName
== NULL
|| attrData
== NULL
||
265 attrStream
== NULL
|| fieldInfo
== NULL
)
266 return SJME_ERROR_NULL_ARGUMENTS
;
268 /* Read the constant value index. */
270 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
271 attrStream
, &index
)) || index
< 0)
272 return sjme_error_default(error
);
274 /* Make sure it is valid. */
275 if (index
<= 0 || index
>= inConstPool
->pool
->length
)
276 return SJME_ERROR_INVALID_CLASS_POOL_INDEX
;
278 /* Process based on the pool type used. */
279 item
= &inConstPool
->pool
->elements
[index
];
280 if (item
->type
== SJME_CLASS_POOL_TYPE_INTEGER
)
282 fieldInfo
->constVal
.type
= SJME_JAVA_TYPE_ID_INTEGER
;
283 fieldInfo
->constVal
.value
.java
.i
= item
->constInteger
.value
;
285 else if (item
->type
== SJME_CLASS_POOL_TYPE_FLOAT
)
287 fieldInfo
->constVal
.type
= SJME_JAVA_TYPE_ID_FLOAT
;
288 fieldInfo
->constVal
.value
.java
.f
= item
->constFloat
.value
;
290 else if (item
->type
== SJME_CLASS_POOL_TYPE_LONG
)
292 fieldInfo
->constVal
.type
= SJME_JAVA_TYPE_ID_LONG
;
293 fieldInfo
->constVal
.value
.java
.j
= item
->constLong
.value
;
295 else if (item
->type
== SJME_CLASS_POOL_TYPE_DOUBLE
)
297 fieldInfo
->constVal
.type
= SJME_JAVA_TYPE_ID_DOUBLE
;
298 fieldInfo
->constVal
.value
.java
.d
= item
->constDouble
.value
;
300 else if (item
->type
== SJME_CLASS_POOL_TYPE_STRING
)
302 fieldInfo
->constVal
.type
= SJME_JAVA_TYPE_ID_OBJECT
;
303 fieldInfo
->constVal
.value
.string
= item
->constString
.value
;
305 /* Count up as we are using it. */
306 if (sjme_error_is(error
= sjme_alloc_weakRef(
307 fieldInfo
->constVal
.value
.string
, NULL
)))
308 return sjme_error_default(error
);
313 return SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
316 return SJME_ERROR_NONE
;
319 static const sjme_class_parseAttributeHandlerInfo sjme_class_fieldAttr
[] =
321 {"ConstantValue", sjme_class_fieldAttrConstantValue
},
325 static sjme_errorCode
sjme_class_fieldFlagsParse(
326 sjme_attrInNotNull sjme_stream_input inStream
,
327 sjme_attrOutNotNull sjme_class_fieldFlags
* outFlags
)
329 sjme_errorCode error
;
330 sjme_jshort rawFlags
;
332 if (inStream
== NULL
|| outFlags
== NULL
)
333 return SJME_ERROR_NULL_ARGUMENTS
;
337 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
338 inStream
, &rawFlags
)) || rawFlags
< 0)
339 return sjme_error_default(error
);
341 /* Translate to bitfield. */
342 memset(outFlags
, 0, sizeof(*outFlags
));
343 if ((rawFlags
& SJME_CLASS_ACC_PUBLIC
) != 0)
344 outFlags
->member
.access
.public = SJME_JNI_TRUE
;
345 if ((rawFlags
& SJME_CLASS_ACC_PRIVATE
) != 0)
346 outFlags
->member
.access
.private = SJME_JNI_TRUE
;
347 if ((rawFlags
& SJME_CLASS_ACC_PROTECTED
) != 0)
348 outFlags
->member
.access
.protected = SJME_JNI_TRUE
;
349 if ((rawFlags
& SJME_CLASS_ACC_STATIC
) != 0)
350 outFlags
->member
.isStatic
= SJME_JNI_TRUE
;
351 if ((rawFlags
& SJME_CLASS_ACC_FINAL
) != 0)
352 outFlags
->member
.final
= SJME_JNI_TRUE
;
353 if ((rawFlags
& SJME_CLASS_ACC_VOLATILE
) != 0)
354 outFlags
->isVolatile
= SJME_JNI_TRUE
;
355 if ((rawFlags
& SJME_CLASS_ACC_TRANSIENT
) != 0)
356 outFlags
->transient
= SJME_JNI_TRUE
;
357 if ((rawFlags
& SJME_CLASS_ACC_ENUM
) != 0)
358 outFlags
->enumeration
= SJME_JNI_TRUE
;
359 if ((rawFlags
& SJME_CLASS_ACC_SYNTHETIC
) != 0)
360 outFlags
->member
.synthetic
= SJME_JNI_TRUE
;
362 /* Can only have a single access mode. */
363 /* Cannot be both final and volatile. */
364 if (((outFlags
->member
.access
.public +
365 outFlags
->member
.access
.protected +
366 outFlags
->member
.access
.private) > 1) ||
367 (outFlags
->member
.final
&& outFlags
->isVolatile
))
368 return SJME_ERROR_INVALID_FIELD_FLAGS
;
371 return SJME_ERROR_NONE
;
374 static sjme_errorCode
sjme_class_methodAttrCode(
375 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
376 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
377 sjme_attrInNotNull sjme_stringPool inStringPool
,
378 sjme_attrInNotNull sjme_pointer context
,
379 sjme_attrInNotNull sjme_lpcstr attrName
,
380 sjme_attrInNotNull sjme_stream_input attrStream
,
381 sjme_attrInNotNullBuf(attrLen
) sjme_pointer attrData
,
382 sjme_attrInPositive sjme_jint attrLen
)
384 sjme_errorCode error
;
385 sjme_jshort maxStack
, maxLocals
, numExcept
;
386 sjme_jint codeLen
, i
, actualCodeLen
;
387 sjme_class_methodInfo methodInfo
;
388 sjme_class_codeInfo result
;
389 sjme_jubyte
* rawCode
;
390 sjme_list_sjme_class_exceptionHandler
* excepts
;
391 sjme_class_exceptionHandler
* except
;
393 methodInfo
= context
;
394 if (inPool
== NULL
|| inConstPool
== NULL
|| inStringPool
== NULL
||
395 context
== NULL
|| attrName
== NULL
|| attrData
== NULL
||
396 attrStream
== NULL
|| methodInfo
== NULL
)
397 return SJME_ERROR_NULL_ARGUMENTS
;
399 /* Can only have one. */
400 if (methodInfo
->code
!= NULL
)
401 return SJME_ERROR_METHOD_MULTIPLE_CODE
;
403 /* Make sure we can allocate this. */
405 if (sjme_error_is(error
= sjme_nvm_alloc(inPool
,
406 sizeof(*result
), SJME_NVM_STRUCT_CODE
,
407 SJME_AS_NVM_COMMONP(&result
))) || result
== NULL
)
408 goto fail_allocResult
;
410 /* In this method! */
411 result
->inMethod
= methodInfo
;
413 /* Read in max stack and locals. */
415 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
416 attrStream
, &maxStack
)) || maxStack
< 0)
417 goto fail_readMaxStack
;
419 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
420 attrStream
, &maxLocals
)) || maxLocals
< 0)
421 goto fail_readMaxLocals
;
424 result
->maxStack
= maxStack
;
425 result
->maxLocals
= maxLocals
;
427 /* Read in code length. */
429 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
430 attrStream
, &codeLen
)) || codeLen
<= 0)
431 goto fail_readCodeLen
;
434 rawCode
= sjme_alloca(codeLen
);
437 error
= SJME_ERROR_OUT_OF_MEMORY
;
438 goto fail_allocRawCode
;
440 memset(rawCode
, 0, codeLen
);
443 if (sjme_error_is(error
= sjme_stream_inputReadFully(
444 attrStream
, &actualCodeLen
,
445 rawCode
, codeLen
)) ||
446 actualCodeLen
!= codeLen
)
447 goto fail_readRawCode
;
449 /* Read in exception table count. */
451 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
452 attrStream
, &numExcept
)) || numExcept
< 0)
453 goto fail_readNumExcept
;
455 /* Only if there are actual exceptions. */
459 /* Allocate base table. */
460 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
461 numExcept
, &excepts
, sjme_class_exceptionHandler
, 0)) ||
463 goto fail_allocExcepts
;
464 result
->exceptions
= excepts
;
466 /* Read in each exception. */
467 for (i
= 0; i
< numExcept
; i
++)
469 /* Which is being read into? */
470 except
= &excepts
->elements
[i
];
472 /* Read in values. */
473 except
->range
.start
= -1;
474 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
475 attrStream
, &except
->range
.start
)) ||
476 except
->range
.start
< 0)
477 goto fail_exceptShorts
;
478 except
->range
.end
= -1;
479 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
480 attrStream
, &except
->range
.end
)) ||
481 except
->range
.end
< 0)
482 goto fail_exceptShorts
;
483 except
->handlerPc
= -1;
484 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
485 attrStream
, &except
->handlerPc
)) ||
486 except
->handlerPc
< 0)
487 goto fail_exceptShorts
;
489 /* Read in handler class. */
490 except
->handles
= NULL
;
491 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
492 attrStream
, inConstPool
,
493 SJME_CLASS_POOL_TYPE_CLASS
,
495 (sjme_class_poolEntry
**)&except
->handles
)))
496 goto fail_exceptHandles
;
500 /* Parse attributes. */
501 if (sjme_error_is(error
= sjme_class_parseAttributes(
502 inPool
, attrStream
, inConstPool
, inStringPool
,
503 sjme_class_codeAttr
, result
)))
504 goto fail_parseAttributes
;
506 /* Make sure the code is referenced. */
507 methodInfo
->code
= result
;
508 if (sjme_error_is(error
= sjme_alloc_weakRef(result
, NULL
)))
512 return SJME_ERROR_NONE
;
514 fail_parseAttributes
:
526 sjme_closeable_close(SJME_AS_CLOSEABLE(result
));
527 return sjme_error_default(error
);
530 static const sjme_class_parseAttributeHandlerInfo sjme_class_methodAttr
[] =
532 {"Code", sjme_class_methodAttrCode
},
536 static sjme_errorCode
sjme_class_methodFlagsParse(
537 sjme_attrInNotNull sjme_stream_input inStream
,
538 sjme_attrOutNotNull sjme_class_methodFlags
* outFlags
)
540 sjme_errorCode error
;
541 sjme_jshort rawFlags
;
543 if (inStream
== NULL
|| outFlags
== NULL
)
544 return SJME_ERROR_NULL_ARGUMENTS
;
548 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
549 inStream
, &rawFlags
)) || rawFlags
< 0)
550 return sjme_error_default(error
);
552 /* Translate to bitfield. */
553 memset(outFlags
, 0, sizeof(*outFlags
));
554 if ((rawFlags
& SJME_CLASS_ACC_PUBLIC
) != 0)
555 outFlags
->member
.access
.public = SJME_JNI_TRUE
;
556 if ((rawFlags
& SJME_CLASS_ACC_PRIVATE
) != 0)
557 outFlags
->member
.access
.private = SJME_JNI_TRUE
;
558 if ((rawFlags
& SJME_CLASS_ACC_PROTECTED
) != 0)
559 outFlags
->member
.access
.protected = SJME_JNI_TRUE
;
560 if ((rawFlags
& SJME_CLASS_ACC_STATIC
) != 0)
561 outFlags
->member
.isStatic
= SJME_JNI_TRUE
;
562 if ((rawFlags
& SJME_CLASS_ACC_FINAL
) != 0)
563 outFlags
->member
.final
= SJME_JNI_TRUE
;
564 if ((rawFlags
& SJME_CLASS_ACC_SYNCHRONIZED
) != 0)
565 outFlags
->synchronized
= SJME_JNI_TRUE
;
566 if ((rawFlags
& SJME_CLASS_ACC_BRIDGE
) != 0)
567 outFlags
->bridge
= SJME_JNI_TRUE
;
568 if ((rawFlags
& SJME_CLASS_ACC_VARARGS
) != 0)
569 outFlags
->varargs
= SJME_JNI_TRUE
;
570 if ((rawFlags
& SJME_CLASS_ACC_NATIVE
) != 0)
571 outFlags
->native
= SJME_JNI_TRUE
;
572 if ((rawFlags
& SJME_CLASS_ACC_ABSTRACT
) != 0)
573 outFlags
->abstract
= SJME_JNI_TRUE
;
574 if ((rawFlags
& SJME_CLASS_ACC_STRICTFP
) != 0)
575 outFlags
->strictfp
= SJME_JNI_TRUE
;
576 if ((rawFlags
& SJME_CLASS_ACC_SYNTHETIC
) != 0)
577 outFlags
->member
.synthetic
= SJME_JNI_TRUE
;
579 /* Can only have a single access mode. */
580 /* Abstract cannot be final, private, static, strict, or synchronized. */
581 if (((outFlags
->member
.access
.public +
582 outFlags
->member
.access
.protected +
583 outFlags
->member
.access
.private) > 1) ||
584 (outFlags
->abstract
&& (outFlags
->member
.final
||
585 outFlags
->native
|| outFlags
->member
.access
.private ||
586 outFlags
->member
.isStatic
|| outFlags
->strictfp
||
587 outFlags
->synchronized
)))
588 return SJME_ERROR_INVALID_METHOD_FLAGS
;
591 return SJME_ERROR_NONE
;
594 static sjme_errorCode
sjme_class_parseAttribute(
595 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
596 sjme_attrInNotNull sjme_stream_input inStream
,
597 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
598 sjme_attrInNotNull sjme_stringPool inStringPool
,
599 sjme_attrInNotNull
const sjme_class_parseAttributeHandlerInfo
* handlers
,
600 sjme_attrInNotNull sjme_pointer context
,
601 sjme_attrInNotNull sjme_lpcstr attrName
,
602 sjme_attrInPositive sjme_jint attrLen
)
604 sjme_errorCode error
, errorC
;
605 sjme_jubyte
* attrData
;
607 const sjme_class_parseAttributeHandlerInfo
* at
;
608 sjme_stream_input attrStream
;
610 if (inPool
== NULL
|| inStream
== NULL
|| inConstPool
== NULL
||
611 inStringPool
== NULL
|| handlers
== NULL
|| context
== NULL
||
613 return SJME_ERROR_NULL_ARGUMENTS
;
616 return SJME_ERROR_INDEX_OUT_OF_BOUNDS
;
618 /* Allocate buffer to read in the data. */
619 attrData
= sjme_alloca(attrLen
);
620 if (attrData
== NULL
)
621 return SJME_ERROR_OUT_OF_MEMORY
;
622 memset(attrData
, 0, attrLen
);
624 /* Read in everything. */
626 if (sjme_error_is(error
= sjme_stream_inputReadFully(
627 inStream
, &readCount
, attrData
, attrLen
)) ||
629 return sjme_error_default(error
);
631 /* Find and call handler for this. */
632 for (at
= handlers
; at
->name
!= NULL
&& at
->handler
!= NULL
; at
++)
633 if (0 == strcmp(at
->name
, attrName
))
635 /* Load stream over the data. */
637 if (sjme_error_is(error
= sjme_stream_inputOpenMemory(
639 attrData
, attrLen
)) || attrStream
== NULL
)
640 return sjme_error_default(error
);
643 error
= at
->handler(inPool
, inConstPool
, inStringPool
, context
,
644 attrName
, attrStream
, attrData
, attrLen
);
647 if (sjme_error_is(errorC
= sjme_closeable_close(
648 SJME_AS_CLOSEABLE(attrStream
))))
649 return sjme_error_defaultOr(error
, errorC
);
652 if (sjme_error_is(error
))
653 return sjme_error_default(error
);
657 #if defined(SJME_CONFIG_DEBUG)
659 sjme_message("No handler for attribute %s.", attrName
);
662 /* None found, so ignore it. */
663 return SJME_ERROR_NONE
;
666 sjme_errorCode
sjme_class_parse(
667 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
668 sjme_attrInNotNull sjme_stream_input inStream
,
669 sjme_attrInNotNull sjme_stringPool inStringPool
,
670 sjme_attrOutNotNull sjme_class_info
* outClass
)
672 sjme_errorCode error
;
673 sjme_jint magic
, fullVersion
, i
;
674 sjme_jshort major
, minor
, interfaceCount
, fieldCount
, methodCount
;
675 sjme_class_version actualVersion
;
676 sjme_class_poolInfo pool
;
677 sjme_class_info result
;
678 sjme_class_poolEntry
* thisName
;
679 sjme_class_poolEntry
* superName
;
680 sjme_class_poolEntry
* interfaceName
;
681 sjme_list_sjme_stringPool_string
* interfaceNames
;
682 sjme_list_sjme_class_fieldInfo
* fields
;
683 sjme_list_sjme_class_methodInfo
* methods
;
685 if (inPool
== NULL
|| inStream
== NULL
|| inStringPool
== NULL
||
687 return SJME_ERROR_NONE
;
689 /* Make sure we can actually allocate the resultant class. */
691 if (sjme_error_is(error
= sjme_nvm_alloc(inPool
,
692 sizeof(*result
), SJME_NVM_STRUCT_CLASS_INFO
,
693 SJME_AS_NVM_COMMONP(&result
))) || result
== NULL
)
694 goto fail_allocResult
;
696 /* Read in magic number. */
698 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
702 /* It must be valid! */
703 if (magic
!= SJME_CLASS_MAGIC
)
705 error
= SJME_ERROR_INVALID_CLASS_MAGIC
;
709 /* Read in version info. */
711 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
716 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
720 /* Compose and find matching version. */
721 fullVersion
= (major
<< 16) | (minor
& 0xFFFF);
722 if (fullVersion
>= SJME_CLASS_CLDC_1_0
&&
723 fullVersion
<= SJME_CLASS_CLDC_1_0_MAX
)
724 actualVersion
= SJME_CLASS_CLDC_1_0
;
725 else if (fullVersion
>= SJME_CLASS_CLDC_1_1
&&
726 fullVersion
<= SJME_CLASS_CLDC_1_1_MAX
)
727 actualVersion
= SJME_CLASS_CLDC_1_1
;
728 else if (fullVersion
>= SJME_CLASS_CLDC_1_8
&&
729 fullVersion
<= SJME_CLASS_CLDC_1_8_MAX
)
730 actualVersion
= SJME_CLASS_CLDC_1_8
;
735 error
= SJME_ERROR_INVALID_CLASS_VERSION
;
736 goto fail_badVersion
;
740 result
->version
= actualVersion
;
742 /* Parse the constant pool. */
744 if (sjme_error_is(error
= sjme_class_parseConstantPool(
745 inPool
, inStream
, inStringPool
, &pool
)) || pool
== NULL
)
748 /* We are using this, so count it up. */
749 if (sjme_error_is(error
= sjme_alloc_weakRef(pool
, NULL
)))
754 if (sjme_error_is(error
= sjme_class_classFlagsParse(
755 inStream
, &result
->flags
)))
758 /* Read in this name. */
760 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
761 inStream
, result
->pool
,
762 SJME_CLASS_POOL_TYPE_CLASS
,
763 SJME_JNI_FALSE
, &thisName
)) || thisName
== NULL
)
764 goto fail_readThisName
;
767 result
->name
= thisName
->classRef
.descriptor
;
768 if (sjme_error_is(error
= sjme_alloc_weakRef(
769 result
->name
, NULL
)))
770 goto fail_refThisName
;
772 /* Read in super name. */
774 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
775 inStream
, result
->pool
,
776 SJME_CLASS_POOL_TYPE_CLASS
,
777 SJME_JNI_TRUE
, &superName
)))
778 goto fail_readSuperName
;
780 /* Reference it, if valid. */
781 if (superName
!= NULL
)
783 result
->superName
= superName
->classRef
.descriptor
;
784 if (sjme_error_is(error
= sjme_alloc_weakRef(
785 result
->superName
, NULL
)))
786 goto fail_refSuperName
;
789 /* How many interfaces are there? */
791 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
792 inStream
, &interfaceCount
)) || interfaceCount
< 0)
793 goto fail_readInterfaceCount
;
795 /* Allocate interfaces count. */
796 interfaceNames
= NULL
;
797 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
798 interfaceCount
, &interfaceNames
, sjme_stringPool_string
, 0)) ||
799 interfaceNames
== NULL
)
800 goto fail_allocInterfaceNames
;
801 result
->interfaceNames
= interfaceNames
;
803 /* Read in all interfaces. */
804 for (i
= 0; i
< interfaceCount
; i
++)
807 interfaceName
= NULL
;
808 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
809 inStream
, result
->pool
,
810 SJME_CLASS_POOL_TYPE_CLASS
,
811 SJME_JNI_FALSE
, &interfaceName
)) ||
812 interfaceName
== NULL
)
813 goto fail_readThisName
;
816 interfaceNames
->elements
[i
] = interfaceName
->classRef
.descriptor
;
817 if (sjme_error_is(error
= sjme_alloc_weakRef(
818 interfaceNames
->elements
[i
], NULL
)))
819 goto fail_refThisName
;
822 /* Read in field count. */
824 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
825 inStream
, &fieldCount
)) || fieldCount
< 0)
826 goto fail_readFieldCount
;
828 /* Setup list to store fields in. */
830 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
831 fieldCount
, &fields
, sjme_class_fieldInfo
, 0)) || fields
== NULL
)
832 goto fail_allocFields
;
833 result
->fields
= fields
;
835 /* Load in and process each field. */
836 for (i
= 0; i
< fieldCount
; i
++)
838 /* Parse each field. */
839 if (sjme_error_is(error
= sjme_class_parseField(
840 inPool
, inStream
, result
->pool
, inStringPool
,
841 &fields
->elements
[i
])) ||
842 fields
->elements
[i
] == NULL
)
843 goto fail_parseField
;
845 /* We are referencing this. */
846 if (sjme_error_is(error
= sjme_alloc_weakRef(
847 fields
->elements
[i
], NULL
)))
851 /* Read in method count. */
853 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
854 inStream
, &methodCount
)) || methodCount
< 0)
855 goto fail_readMethodCount
;
857 /* Setup list to store methods in. */
859 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
860 methodCount
, &methods
, sjme_class_methodInfo
, 0)) || methods
== NULL
)
861 goto fail_allocMethods
;
862 result
->methods
= methods
;
864 /* Load in and process each method. */
865 for (i
= 0; i
< methodCount
; i
++)
867 /* Parse each method. */
868 if (sjme_error_is(error
= sjme_class_parseMethod(
869 inPool
, inStream
, result
->pool
, inStringPool
,
870 &methods
->elements
[i
])) ||
871 methods
->elements
[i
] == NULL
)
872 goto fail_parseMethod
;
874 /* Reference as we are using this. */
875 if (sjme_error_is(error
= sjme_alloc_weakRef(
876 methods
->elements
[i
], NULL
)))
880 /* Parse attributes. */
881 if (sjme_error_is(error
= sjme_class_parseAttributes(
882 inPool
, inStream
, result
->pool
, inStringPool
,
883 sjme_class_classAttr
, result
)))
884 goto fail_parseAttributes
;
888 return SJME_ERROR_NONE
;
890 fail_parseAttributes
:
894 fail_readMethodCount
:
899 fail_allocInterfaceNames
:
900 fail_readInterfaceCount
:
916 sjme_closeable_close(SJME_AS_CLOSEABLE(result
));
917 return sjme_error_default(error
);
920 sjme_errorCode
sjme_class_parseAttributes(
921 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
922 sjme_attrInNotNull sjme_stream_input inStream
,
923 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
924 sjme_attrInNotNull sjme_stringPool inStringPool
,
925 sjme_attrInNotNull
const sjme_class_parseAttributeHandlerInfo
* handlers
,
926 sjme_attrInNotNull sjme_pointer context
)
928 sjme_errorCode error
;
931 sjme_class_poolEntry
* name
;
933 if (inPool
== NULL
|| inStream
== NULL
|| inConstPool
== NULL
||
934 inStringPool
== NULL
|| handlers
== NULL
|| context
== NULL
)
935 return SJME_ERROR_NULL_ARGUMENTS
;
939 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
940 inStream
, &count
)) || count
< 0)
943 /* Read individual attributes. */
944 for (i
= 0; i
< count
; i
++)
948 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
949 inStream
, inConstPool
,
950 SJME_CLASS_POOL_TYPE_UTF
,
951 SJME_JNI_FALSE
, &name
)) || name
== NULL
)
954 /* Read in length. */
956 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
957 inStream
, &len
)) || len
< 0)
960 /* Stage it for stack allocations. */
961 if (sjme_error_is(error
= sjme_class_parseAttribute(
962 inPool
, inStream
, inConstPool
, inStringPool
, handlers
,
963 context
, (sjme_lpcstr
)&name
->utf
.utf
->chars
[0],
965 goto fail_parseSingle
;
969 return SJME_ERROR_NONE
;
975 return sjme_error_default(error
);
978 sjme_errorCode
sjme_class_parseConstantPool(
979 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
980 sjme_attrInNotNull sjme_stream_input inStream
,
981 sjme_attrInNotNull sjme_stringPool inStringPool
,
982 sjme_attrOutNotNull sjme_class_poolInfo
* outPool
)
984 sjme_errorCode error
;
988 sjme_list_sjme_class_poolEntry
* entries
;
989 sjme_class_poolEntry
* entry
;
990 sjme_class_poolEntry
* target
;
991 sjme_stringPool_string utf
;
992 sjme_class_poolInfo result
;
994 if (inPool
== NULL
|| inStream
== NULL
|| outPool
== NULL
||
995 inStringPool
== NULL
)
996 return SJME_ERROR_NULL_ARGUMENTS
;
998 /* Make sure we can actually allocate this. */
1000 if (sjme_error_is(error
= sjme_nvm_alloc(inPool
,
1001 sizeof(*result
), SJME_NVM_STRUCT_POOL
,
1002 SJME_AS_NVM_COMMONP(&result
))) || result
== NULL
)
1003 goto fail_allocResult
;
1005 /* Read in pool count. */
1007 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
1008 inStream
, &count
)) || count
< 0)
1009 goto fail_readCount
;
1011 /* Invalid pool size? */
1012 if (count
< 0 || count
>= INT16_MAX
)
1014 error
= SJME_ERROR_INVALID_CLASS_POOL_COUNT
;
1015 goto fail_poolCount
;
1018 /* Count up by one, since zero is included! */
1021 /* Allocate resultant entries, where they will all go. */
1023 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
1024 count
, &entries
, sjme_class_poolEntry
, 0)) || entries
== NULL
)
1025 goto fail_entryList
;
1026 result
->pool
= entries
;
1028 /* Read in all entries. */
1029 /* This is a first pass since index items can refer to later entries. */
1030 for (index
= 1; index
< count
- 1; index
++)
1032 /* Which entry is being written? */
1033 entry
= &entries
->elements
[index
];
1037 if (sjme_error_is(error
= sjme_stream_inputReadValueJB(
1038 inStream
, &tag
)) || tag
< 0)
1042 sjme_message("TAG: %d", tag
);
1047 /* Which tag is this? */
1050 /* Class reference. */
1051 case SJME_CLASS_POOL_TYPE_CLASS
:
1052 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
1054 &entry
->classRef
.descriptorIndex
)))
1059 case SJME_CLASS_POOL_TYPE_DOUBLE
:
1060 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
1062 (sjme_jint
*)&entry
->constDouble
.value
.hi
)))
1064 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
1066 (sjme_jint
*)&entry
->constDouble
.value
.lo
)))
1069 /* Skip wide index. */
1073 /* Reference to a member. */
1074 case SJME_CLASS_POOL_TYPE_FIELD
:
1075 case SJME_CLASS_POOL_TYPE_INTERFACE_METHOD
:
1076 case SJME_CLASS_POOL_TYPE_METHOD
:
1077 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
1079 &entry
->member
.inClassIndex
)))
1081 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
1083 &entry
->member
.nameAndTypeIndex
)))
1088 case SJME_CLASS_POOL_TYPE_FLOAT
:
1089 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
1091 (sjme_jint
*)&entry
->constFloat
.value
.value
)))
1095 /* Integer value. */
1096 case SJME_CLASS_POOL_TYPE_INTEGER
:
1097 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
1099 (sjme_jint
*)&entry
->constInteger
.value
)))
1104 case SJME_CLASS_POOL_TYPE_LONG
:
1105 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
1107 (sjme_jint
*)&entry
->constLong
.value
.part
.hi
)))
1109 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
1111 (sjme_jint
*)&entry
->constLong
.value
.part
.lo
)))
1114 /* Skip wide index. */
1118 /* Name and type information. */
1119 case SJME_CLASS_POOL_TYPE_NAME_AND_TYPE
:
1120 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
1122 &entry
->nameAndType
.nameIndex
)))
1124 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
1126 &entry
->nameAndType
.descriptorIndex
)))
1130 /* Constant string. */
1131 case SJME_CLASS_POOL_TYPE_STRING
:
1132 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
1134 &entry
->constString
.valueIndex
)))
1139 case SJME_CLASS_POOL_TYPE_UTF
:
1141 if (sjme_error_is(error
= sjme_stringPool_locateStream(
1142 inStringPool
, inStream
, &utf
)) || utf
== NULL
)
1146 sjme_message("Read UTF: %s",
1149 /* Store and count up entry as we are using it now. */
1150 entry
->utf
.utf
= utf
;
1151 if (sjme_error_is(error
= sjme_alloc_weakRef(
1157 sjme_todo("Impl? %d", tag
);
1158 return SJME_ERROR_NOT_IMPLEMENTED
;
1162 /* Second stage item linking. */
1163 for (index
= 1; index
< count
- 1; index
++)
1165 /* Which entry is being initialized? */
1166 entry
= &entries
->elements
[index
];
1168 /* Initialize accordingly. */
1169 switch (entry
->type
)
1171 /* These are base elements that need no initialization. */
1172 case SJME_CLASS_POOL_TYPE_UTF
:
1173 case SJME_CLASS_POOL_TYPE_INTEGER
:
1174 case SJME_CLASS_POOL_TYPE_FLOAT
:
1177 /* Skip wide element. */
1178 case SJME_CLASS_POOL_TYPE_LONG
:
1179 case SJME_CLASS_POOL_TYPE_DOUBLE
:
1184 case SJME_CLASS_POOL_TYPE_CLASS
:
1185 if (entry
->classRef
.descriptorIndex
<= 0 ||
1186 entry
->classRef
.descriptorIndex
>= entries
->length
)
1188 error
= SJME_ERROR_INVALID_CLASS_POOL_INDEX
;
1192 /* Needs to be a UTF string. */
1193 target
= &entries
->elements
[entry
->classRef
.descriptorIndex
];
1194 if (target
->type
!= SJME_CLASS_POOL_TYPE_UTF
)
1196 error
= SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
1200 /* Refer to it and count up, since we are using it. */
1201 entry
->classRef
.descriptor
= target
->utf
.utf
;
1202 if (sjme_error_is(error
= sjme_alloc_weakRef(
1203 entry
->classRef
.descriptor
, NULL
)))
1207 /* Member reference. */
1208 case SJME_CLASS_POOL_TYPE_FIELD
:
1209 case SJME_CLASS_POOL_TYPE_INTERFACE_METHOD
:
1210 case SJME_CLASS_POOL_TYPE_METHOD
:
1211 if (entry
->member
.inClassIndex
<= 0 ||
1212 entry
->member
.inClassIndex
>= entries
->length
||
1213 entry
->member
.nameAndTypeIndex
<= 0 ||
1214 entry
->member
.nameAndTypeIndex
>= entries
->length
)
1216 error
= SJME_ERROR_INVALID_CLASS_POOL_INDEX
;
1220 /* Needs to be a class. */
1221 target
= &entries
->elements
[entry
->member
.inClassIndex
];
1222 if (target
->type
!= SJME_CLASS_POOL_TYPE_CLASS
)
1224 error
= SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
1229 entry
->member
.inClass
=
1230 (const sjme_class_poolEntryClass
*)target
;
1232 /* Needs to be a name and type. */
1233 target
= &entries
->elements
[entry
->member
.nameAndTypeIndex
];
1234 if (target
->type
!= SJME_CLASS_POOL_TYPE_NAME_AND_TYPE
)
1236 error
= SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
1240 /* Set name and type. */
1241 entry
->member
.nameAndType
=
1242 (const sjme_class_poolEntryNameAndType
*)target
;
1245 case SJME_CLASS_POOL_TYPE_NAME_AND_TYPE
:
1246 if (entry
->nameAndType
.nameIndex
<= 0 ||
1247 entry
->nameAndType
.nameIndex
>= entries
->length
||
1248 entry
->nameAndType
.descriptorIndex
<= 0 ||
1249 entry
->nameAndType
.descriptorIndex
>= entries
->length
)
1251 error
= SJME_ERROR_INVALID_CLASS_POOL_INDEX
;
1255 /* Needs to be UTF. */
1256 target
= &entries
->elements
[entry
->nameAndType
.nameIndex
];
1257 if (target
->type
!= SJME_CLASS_POOL_TYPE_UTF
)
1259 error
= SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
1264 entry
->nameAndType
.name
= target
->utf
.utf
;
1265 if (sjme_error_is(error
= sjme_alloc_weakRef(
1266 entry
->nameAndType
.name
, NULL
)))
1269 /* Needs to be UTF. */
1270 target
= &entries
->elements
[
1271 entry
->nameAndType
.descriptorIndex
];
1272 if (target
->type
!= SJME_CLASS_POOL_TYPE_UTF
)
1274 error
= SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
1278 /* Set descriptor. */
1279 entry
->nameAndType
.descriptor
= target
->utf
.utf
;
1280 if (sjme_error_is(error
= sjme_alloc_weakRef(
1281 entry
->nameAndType
.descriptor
, NULL
)))
1285 /* Constant string. */
1286 case SJME_CLASS_POOL_TYPE_STRING
:
1287 if (entry
->constString
.valueIndex
<= 0 ||
1288 entry
->constString
.valueIndex
>= entries
->length
)
1290 error
= SJME_ERROR_INVALID_CLASS_POOL_INDEX
;
1294 /* Needs to be a UTF string. */
1295 target
= &entries
->elements
[entry
->constString
.valueIndex
];
1296 if (target
->type
!= SJME_CLASS_POOL_TYPE_UTF
)
1298 error
= SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
1302 /* Refer to it and count up, since we are using it. */
1303 entry
->constString
.value
= target
->utf
.utf
;
1304 if (sjme_error_is(error
= sjme_alloc_weakRef(
1305 entry
->constString
.value
, NULL
)))
1310 sjme_todo("Impl? %d", tag
);
1311 return SJME_ERROR_NOT_IMPLEMENTED
;
1317 return SJME_ERROR_NONE
;
1323 if (entries
!= NULL
)
1324 sjme_alloc_free(entries
);
1330 sjme_closeable_close(SJME_AS_CLOSEABLE(result
));
1331 return sjme_error_default(error
);
1334 sjme_errorCode
sjme_class_parseField(
1335 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
1336 sjme_attrInNotNull sjme_stream_input inStream
,
1337 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
1338 sjme_attrInNotNull sjme_stringPool inStringPool
,
1339 sjme_attrOutNotNull sjme_class_fieldInfo
* outField
)
1341 sjme_errorCode error
;
1342 sjme_class_fieldInfo result
;
1343 sjme_class_poolEntry
* name
;
1344 sjme_class_poolEntry
* type
;
1346 if (inPool
== NULL
|| inStream
== NULL
|| inConstPool
== NULL
||
1347 outField
== NULL
|| inStringPool
== NULL
)
1348 return SJME_ERROR_NULL_ARGUMENTS
;
1350 /* Ensure we can allocate the result first. */
1352 if (sjme_error_is(error
= sjme_nvm_alloc(inPool
,
1353 sizeof(*result
), SJME_NVM_STRUCT_FIELD_INFO
,
1354 SJME_AS_NVM_COMMONP(&result
))) || result
== NULL
)
1355 goto fail_allocResult
;
1357 /* Read in flags. */
1358 if (sjme_error_is(error
= sjme_class_fieldFlagsParse(
1359 inStream
, &result
->flags
)))
1360 goto fail_readFlags
;
1364 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
1365 inStream
, inConstPool
,
1366 SJME_CLASS_POOL_TYPE_UTF
,
1367 SJME_JNI_FALSE
, &name
)) || name
== NULL
)
1371 result
->name
= name
->utf
.utf
;
1372 if (sjme_error_is(error
= sjme_alloc_weakRef(
1373 result
->name
, NULL
)))
1378 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
1379 inStream
, inConstPool
,
1380 SJME_CLASS_POOL_TYPE_UTF
,
1381 SJME_JNI_FALSE
, &type
)) || name
== NULL
)
1385 result
->type
= name
->utf
.utf
;
1386 if (sjme_error_is(error
= sjme_alloc_weakRef(
1387 result
->type
, NULL
)))
1390 /* Parse attributes. */
1391 if (sjme_error_is(error
= sjme_class_parseAttributes(
1392 inPool
, inStream
, inConstPool
, inStringPool
,
1393 sjme_class_fieldAttr
, result
)))
1394 goto fail_parseAttributes
;
1398 return SJME_ERROR_NONE
;
1400 fail_parseAttributes
:
1409 sjme_closeable_close(SJME_AS_CLOSEABLE(result
));
1410 return sjme_error_default(error
);
1413 sjme_errorCode
sjme_class_parseMethod(
1414 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
1415 sjme_attrInNotNull sjme_stream_input inStream
,
1416 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
1417 sjme_attrInNotNull sjme_stringPool inStringPool
,
1418 sjme_attrInOutNotNull sjme_class_methodInfo
* outMethod
)
1420 sjme_errorCode error
;
1421 sjme_class_methodInfo result
;
1422 sjme_class_poolEntry
* name
;
1423 sjme_class_poolEntry
* type
;
1425 if (inPool
== NULL
|| inStream
== NULL
|| inConstPool
== NULL
||
1426 outMethod
== NULL
|| inStringPool
== NULL
)
1427 return SJME_ERROR_NULL_ARGUMENTS
;
1429 /* Ensure we can allocate the result first. */
1431 if (sjme_error_is(error
= sjme_nvm_alloc(inPool
,
1432 sizeof(*result
), SJME_NVM_STRUCT_METHOD_INFO
,
1433 SJME_AS_NVM_COMMONP(&result
))) || result
== NULL
)
1434 goto fail_allocResult
;
1436 /* Read in flags. */
1437 if (sjme_error_is(error
= sjme_class_methodFlagsParse(
1438 inStream
, &result
->flags
)))
1439 goto fail_readFlags
;
1443 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
1444 inStream
, inConstPool
,
1445 SJME_CLASS_POOL_TYPE_UTF
,
1446 SJME_JNI_FALSE
, &name
)) || name
== NULL
)
1450 result
->name
= name
->utf
.utf
;
1451 if (sjme_error_is(error
= sjme_alloc_weakRef(
1452 result
->name
, NULL
)))
1457 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
1458 inStream
, inConstPool
,
1459 SJME_CLASS_POOL_TYPE_UTF
,
1460 SJME_JNI_FALSE
, &type
)) || name
== NULL
)
1464 result
->type
= name
->utf
.utf
;
1465 if (sjme_error_is(error
= sjme_alloc_weakRef(
1466 result
->type
, NULL
)))
1469 /* Parse attributes. */
1470 if (sjme_error_is(error
= sjme_class_parseAttributes(
1471 inPool
, inStream
, inConstPool
, inStringPool
,
1472 sjme_class_methodAttr
, result
)))
1473 goto fail_parseAttributes
;
1476 *outMethod
= result
;
1477 return SJME_ERROR_NONE
;
1479 fail_parseAttributes
:
1488 sjme_closeable_close(SJME_AS_CLOSEABLE(result
));
1489 return sjme_error_default(error
);