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 // -------------------------------------------------------------------------*/
10 #include "sjme/nvm/classy.h"
11 #include "sjme/debug.h"
12 #include "sjme/cleanup.h"
14 /** The magic number for classes. */
15 #define SJME_CLASS_MAGIC INT32_C(0xCAFEBABE)
17 /** CLDC 1.1 max version (JSR 30). */
18 #define SJME_CLASS_CLDC_1_0_MAX INT32_C(3080191)
20 /** CLDC 1.1 max version. (JSR 139). */
21 #define SJME_CLASS_CLDC_1_1_MAX INT32_C(3342335)
23 /** CLDC 8 max version. */
24 #define SJME_CLASS_CLDC_1_8_MAX INT32_C(3407872)
27 #define SJME_CLASS_ACC_PUBLIC INT16_C(0x0001)
30 #define SJME_CLASS_ACC_PRIVATE INT16_C(0x0002)
33 #define SJME_CLASS_ACC_PROTECTED INT16_C(0x0004)
36 #define SJME_CLASS_ACC_STATIC INT16_C(0x0008)
38 /** Final class or member. */
39 #define SJME_CLASS_ACC_FINAL INT16_C(0x0010)
41 /** Alternative @c invokesuper logic. */
42 #define SJME_CLASS_ACC_SUPER INT16_C(0x0020)
44 /** Synchronized method. */
45 #define SJME_CLASS_ACC_SYNCHRONIZED INT16_C(0x0020)
48 #define SJME_CLASS_ACC_BRIDGE INT16_C(0x0040)
50 /** Variable arguments. */
51 #define SJME_CLASS_ACC_VARARGS INT16_C(0x0080)
54 #define SJME_CLASS_ACC_NATIVE INT16_C(0x0100)
56 /** Class is an interface. */
57 #define SJME_CLASS_ACC_INTERFACE INT16_C(0x0200)
59 /** Abstract class or method. */
60 #define SJME_CLASS_ACC_ABSTRACT INT16_C(0x0400)
62 /** Strict floating point method. */
63 #define SJME_CLASS_ACC_STRICTFP INT16_C(0x0800)
65 /** Synthetic class or member. */
66 #define SJME_CLASS_ACC_SYNTHETIC INT16_C(0x1000)
68 /** Class is an annotation. */
69 #define SJME_CLASS_ACC_ANNOTATION INT16_C(0x2000)
71 /** Class is an enum. */
72 #define SJME_CLASS_ACC_ENUM INT16_C(0x4000)
74 static sjme_errorCode
sjme_class_classAttr(
75 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
76 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
77 sjme_attrInNotNull sjme_stringPool inStringPool
,
78 sjme_attrInNotNull sjme_pointer context
,
79 sjme_attrInNotNull sjme_lpcstr attrName
,
80 sjme_attrInNotNullBuf(attrLen
) sjme_pointer attrBuf
,
81 sjme_attrInPositive sjme_jint attrLen
)
83 if (inPool
== NULL
|| inConstPool
== NULL
|| inStringPool
== NULL
||
84 context
== NULL
|| attrName
== NULL
|| attrBuf
== NULL
)
85 return SJME_ERROR_NULL_ARGUMENTS
;
88 return SJME_ERROR_NOT_IMPLEMENTED
;
91 static sjme_errorCode
sjme_class_classFlagsParse(
92 sjme_attrInNotNull sjme_stream_input inStream
,
93 sjme_attrOutNotNull sjme_class_classFlags
* outFlags
)
98 if (inStream
== NULL
|| outFlags
== NULL
)
99 return SJME_ERROR_NULL_ARGUMENTS
;
103 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
104 inStream
, &rawFlags
)) || rawFlags
< 0)
105 return sjme_error_default(error
);
107 /* Translate to bitfield. */
108 if ((rawFlags
& SJME_CLASS_ACC_PUBLIC
) != 0)
109 outFlags
->access
.public = SJME_JNI_TRUE
;
110 if ((rawFlags
& SJME_CLASS_ACC_FINAL
) != 0)
111 outFlags
->final
= SJME_JNI_TRUE
;
112 if ((rawFlags
& SJME_CLASS_ACC_SUPER
) != 0)
113 outFlags
->super
= SJME_JNI_TRUE
;
114 if ((rawFlags
& SJME_CLASS_ACC_INTERFACE
) != 0)
115 outFlags
->interface
= SJME_JNI_TRUE
;
116 if ((rawFlags
& SJME_CLASS_ACC_ABSTRACT
) != 0)
117 outFlags
->abstract
= SJME_JNI_TRUE
;
118 if ((rawFlags
& SJME_CLASS_ACC_SYNTHETIC
) != 0)
119 outFlags
->synthetic
= SJME_JNI_TRUE
;
120 if ((rawFlags
& SJME_CLASS_ACC_ANNOTATION
) != 0)
121 outFlags
->annotation
= SJME_JNI_TRUE
;
122 if ((rawFlags
& SJME_CLASS_ACC_ENUM
) != 0)
123 outFlags
->enumeration
= SJME_JNI_TRUE
;
125 /* Cannot be abstract and final. */
126 /* Annotation must be an interface. */
127 /* Interface must be abstract and not final, super, or enum */
128 if ((outFlags
->abstract
&& outFlags
->final
) ||
129 (outFlags
->annotation
&& !outFlags
->interface
) ||
130 (outFlags
->interface
&& (!outFlags
->abstract
||
131 outFlags
->final
|| outFlags
->super
|| outFlags
->enumeration
)))
132 return SJME_ERROR_INVALID_CLASS_FLAGS
;
135 return SJME_ERROR_NONE
;
138 static sjme_errorCode
sjme_class_readPoolRefIndex(
139 sjme_attrInNotNull sjme_stream_input inStream
,
140 sjme_attrInNotNull sjme_class_poolInfo inClassPool
,
141 sjme_attrInPositiveNonZero sjme_class_poolType desireType
,
142 sjme_attrInValue sjme_jboolean canNull
,
143 sjme_attrOutNotNull sjme_class_poolEntry
** outEntry
)
145 sjme_errorCode error
;
147 sjme_class_poolEntry
* result
;
149 if (inStream
== NULL
|| inClassPool
== NULL
|| outEntry
== NULL
)
150 return SJME_ERROR_NULL_ARGUMENTS
;
154 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
156 return sjme_error_default(error
);
158 /* Not a valid index? */
159 if (index
<= 0 || index
>= inClassPool
->pool
->length
)
160 return SJME_ERROR_INVALID_CLASS_POOL_INDEX
;
162 /* Must be the desired type. */
163 result
= &inClassPool
->pool
->elements
[index
];
164 if (result
->type
!= desireType
)
165 return SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
169 return SJME_ERROR_NONE
;
172 static sjme_errorCode
sjme_class_fieldAttr(
173 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
174 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
175 sjme_attrInNotNull sjme_stringPool inStringPool
,
176 sjme_attrInNotNull sjme_pointer context
,
177 sjme_attrInNotNull sjme_lpcstr attrName
,
178 sjme_attrInNotNullBuf(attrLen
) sjme_pointer attrBuf
,
179 sjme_attrInPositive sjme_jint attrLen
)
181 if (inPool
== NULL
|| inConstPool
== NULL
|| inStringPool
== NULL
||
182 context
== NULL
|| attrName
== NULL
|| attrBuf
== NULL
)
183 return SJME_ERROR_NULL_ARGUMENTS
;
186 return SJME_ERROR_NOT_IMPLEMENTED
;
189 static sjme_errorCode
sjme_class_methodAttr(
190 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
191 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
192 sjme_attrInNotNull sjme_stringPool inStringPool
,
193 sjme_attrInNotNull sjme_pointer context
,
194 sjme_attrInNotNull sjme_lpcstr attrName
,
195 sjme_attrInNotNullBuf(attrLen
) sjme_pointer attrBuf
,
196 sjme_attrInPositive sjme_jint attrLen
)
198 if (inPool
== NULL
|| inConstPool
== NULL
|| inStringPool
== NULL
||
199 context
== NULL
|| attrName
== NULL
|| attrBuf
== NULL
)
200 return SJME_ERROR_NULL_ARGUMENTS
;
203 return SJME_ERROR_NOT_IMPLEMENTED
;
206 static sjme_errorCode
sjme_class_methodFlagsParse(
207 sjme_attrInNotNull sjme_stream_input inStream
,
208 sjme_attrOutNotNull sjme_class_methodFlags
* outFlags
)
210 sjme_errorCode error
;
211 sjme_jshort rawFlags
;
213 if (inStream
== NULL
|| outFlags
== NULL
)
214 return SJME_ERROR_NULL_ARGUMENTS
;
218 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
219 inStream
, &rawFlags
)) || rawFlags
< 0)
220 return sjme_error_default(error
);
222 /* Translate to bitfield. */
223 if ((rawFlags
& SJME_CLASS_ACC_PUBLIC
) != 0)
224 outFlags
->member
.access
.public = SJME_JNI_TRUE
;
225 if ((rawFlags
& SJME_CLASS_ACC_PRIVATE
) != 0)
226 outFlags
->member
.access
.private = SJME_JNI_TRUE
;
227 if ((rawFlags
& SJME_CLASS_ACC_PROTECTED
) != 0)
228 outFlags
->member
.access
.protected = SJME_JNI_TRUE
;
229 if ((rawFlags
& SJME_CLASS_ACC_STATIC
) != 0)
230 outFlags
->member
.isStatic
= SJME_JNI_TRUE
;
231 if ((rawFlags
& SJME_CLASS_ACC_FINAL
) != 0)
232 outFlags
->member
.final
= SJME_JNI_TRUE
;
233 if ((rawFlags
& SJME_CLASS_ACC_SYNCHRONIZED
) != 0)
234 outFlags
->synchronized
= SJME_JNI_TRUE
;
235 if ((rawFlags
& SJME_CLASS_ACC_BRIDGE
) != 0)
236 outFlags
->bridge
= SJME_JNI_TRUE
;
237 if ((rawFlags
& SJME_CLASS_ACC_VARARGS
) != 0)
238 outFlags
->varargs
= SJME_JNI_TRUE
;
239 if ((rawFlags
& SJME_CLASS_ACC_NATIVE
) != 0)
240 outFlags
->native
= SJME_JNI_TRUE
;
241 if ((rawFlags
& SJME_CLASS_ACC_ABSTRACT
) != 0)
242 outFlags
->abstract
= SJME_JNI_TRUE
;
243 if ((rawFlags
& SJME_CLASS_ACC_STRICTFP
) != 0)
244 outFlags
->strictfp
= SJME_JNI_TRUE
;
245 if ((rawFlags
& SJME_CLASS_ACC_SYNTHETIC
) != 0)
246 outFlags
->member
.synthetic
= SJME_JNI_TRUE
;
248 /* Can only have a single access mode. */
249 /* Abstract cannot be final, private, static, strict, or synchronized. */
250 if (((outFlags
->member
.access
.public +
251 outFlags
->member
.access
.protected +
252 outFlags
->member
.access
.private) > 1) ||
253 (outFlags
->abstract
&& (outFlags
->member
.final
||
254 outFlags
->native
|| outFlags
->member
.access
.private ||
255 outFlags
->member
.isStatic
|| outFlags
->strictfp
||
256 outFlags
->synchronized
)))
257 return SJME_ERROR_INVALID_METHOD_FLAGS
;
260 return SJME_ERROR_NONE
;
263 sjme_errorCode
sjme_class_parse(
264 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
265 sjme_attrInNotNull sjme_stream_input inStream
,
266 sjme_attrInNotNull sjme_stringPool inStringPool
,
267 sjme_attrOutNotNull sjme_class_info
* outClass
)
269 sjme_errorCode error
;
270 sjme_jint magic
, fullVersion
, i
;
271 sjme_jshort major
, minor
, interfaceCount
, fieldCount
, methodCount
;
272 sjme_class_version actualVersion
;
273 sjme_class_poolInfo pool
;
274 sjme_class_info result
;
275 sjme_class_poolEntry
* thisName
;
276 sjme_class_poolEntry
* superName
;
277 sjme_class_poolEntry
* interfaceName
;
278 sjme_list_sjme_stringPool_string
* interfaceNames
;
279 sjme_list_sjme_class_fieldInfo
* fields
;
280 sjme_list_sjme_class_methodInfo
* methods
;
282 if (inPool
== NULL
|| inStream
== NULL
|| inStringPool
== NULL
||
284 return SJME_ERROR_NONE
;
286 /* Make sure we can actually allocate the resultant class. */
288 if (sjme_error_is(error
= sjme_alloc_weakNew(inPool
,
289 sizeof(*result
), NULL
, NULL
,
290 (sjme_pointer
*)&result
, NULL
)) || result
== NULL
)
291 goto fail_allocResult
;
294 if (sjme_error_is(error
= sjme_nvm_initCommon(
295 SJME_AS_NVM_COMMON(result
),
296 SJME_NVM_STRUCT_CLASS_INFO
)))
297 goto fail_initResult
;
299 /* Read in magic number. */
301 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
305 /* It must be valid! */
306 if (magic
!= SJME_CLASS_MAGIC
)
308 error
= SJME_ERROR_INVALID_CLASS_MAGIC
;
312 /* Read in version info. */
314 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
319 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
323 /* Compose and find matching version. */
324 fullVersion
= (major
<< 16) | (minor
& 0xFFFF);
325 if (fullVersion
>= SJME_CLASS_CLDC_1_0
&&
326 fullVersion
<= SJME_CLASS_CLDC_1_0_MAX
)
327 actualVersion
= SJME_CLASS_CLDC_1_0
;
328 else if (fullVersion
>= SJME_CLASS_CLDC_1_1
&&
329 fullVersion
<= SJME_CLASS_CLDC_1_1_MAX
)
330 actualVersion
= SJME_CLASS_CLDC_1_1
;
331 else if (fullVersion
>= SJME_CLASS_CLDC_1_8
&&
332 fullVersion
<= SJME_CLASS_CLDC_1_8_MAX
)
333 actualVersion
= SJME_CLASS_CLDC_1_8
;
338 error
= SJME_ERROR_INVALID_CLASS_VERSION
;
339 goto fail_badVersion
;
343 result
->version
= actualVersion
;
345 /* Parse the constant pool. */
347 if (sjme_error_is(error
= sjme_class_parseConstantPool(
348 inPool
, inStream
, inStringPool
, &pool
)) || pool
== NULL
)
351 /* We are using this, so count it up. */
352 if (sjme_error_is(error
= sjme_alloc_weakRef(pool
, NULL
)))
357 if (sjme_error_is(error
= sjme_class_classFlagsParse(
358 inStream
, &result
->flags
)))
361 /* Read in this name. */
363 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
364 inStream
, result
->pool
,
365 SJME_CLASS_POOL_TYPE_CLASS
,
366 SJME_JNI_FALSE
, &thisName
)) || thisName
== NULL
)
367 goto fail_readThisName
;
370 result
->name
= thisName
->classRef
.descriptor
;
371 if (sjme_error_is(error
= sjme_alloc_weakRef(
372 result
->name
, NULL
)))
373 goto fail_refThisName
;
375 /* Read in super name. */
377 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
378 inStream
, result
->pool
,
379 SJME_CLASS_POOL_TYPE_CLASS
,
380 SJME_JNI_TRUE
, &superName
)))
381 goto fail_readSuperName
;
383 /* Reference it, if valid. */
384 if (superName
!= NULL
)
386 result
->superName
= superName
->classRef
.descriptor
;
387 if (sjme_error_is(error
= sjme_alloc_weakRef(
388 result
->superName
, NULL
)))
389 goto fail_refSuperName
;
392 /* How many interfaces are there? */
394 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
395 inStream
, &interfaceCount
)) || interfaceCount
< 0)
396 goto fail_readInterfaceCount
;
398 /* Allocate interfaces count. */
399 interfaceNames
= NULL
;
400 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
401 interfaceCount
, &interfaceNames
, sjme_stringPool_string
, 0)) ||
402 interfaceNames
== NULL
)
403 goto fail_allocInterfaceNames
;
404 result
->interfaceNames
= interfaceNames
;
406 /* Read in all interfaces. */
407 for (i
= 0; i
< interfaceCount
; i
++)
410 interfaceName
= NULL
;
411 if (sjme_error_is(error
= sjme_class_readPoolRefIndex(
412 inStream
, result
->pool
,
413 SJME_CLASS_POOL_TYPE_CLASS
,
414 SJME_JNI_FALSE
, &interfaceName
)) ||
415 interfaceName
== NULL
)
416 goto fail_readThisName
;
419 interfaceNames
->elements
[i
] = interfaceName
->classRef
.descriptor
;
420 if (sjme_error_is(error
= sjme_alloc_weakRef(
421 interfaceNames
->elements
[i
], NULL
)))
422 goto fail_refThisName
;
425 /* Read in field count. */
427 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
428 inStream
, &fieldCount
)) || fieldCount
< 0)
429 goto fail_readFieldCount
;
431 /* Setup list to store fields in. */
433 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
434 fieldCount
, &fields
, sjme_class_fieldInfo
, 0)) || fields
== NULL
)
435 goto fail_allocFields
;
436 result
->fields
= fields
;
438 /* Load in and process each field. */
439 for (i
= 0; i
< fieldCount
; i
++)
441 /* Parse each field. */
442 if (sjme_error_is(error
= sjme_class_parseField(
443 inPool
, inStream
, result
->pool
,
444 &fields
->elements
[i
])) ||
445 fields
->elements
[i
] == NULL
)
446 goto fail_parseField
;
449 /* Read in method count. */
451 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
452 inStream
, &methodCount
)) || methodCount
< 0)
453 goto fail_readMethodCount
;
455 /* Setup list to store methods in. */
457 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
458 methodCount
, &methods
, sjme_class_methodInfo
, 0)) || methods
== NULL
)
459 goto fail_allocMethods
;
460 result
->methods
= methods
;
462 /* Load in and process each method. */
463 for (i
= 0; i
< methodCount
; i
++)
465 /* Parse each method. */
466 if (sjme_error_is(error
= sjme_class_parseMethod(
467 inPool
, inStream
, result
->pool
,
468 &methods
->elements
[i
])) ||
469 methods
->elements
[i
] == NULL
)
470 goto fail_parseMethod
;
473 /* Parse attributes. */
474 if (sjme_error_is(error
= sjme_class_parseAttributes(
475 inPool
, inStream
, result
->pool
, inStringPool
,
476 sjme_class_classAttr
, result
)))
477 goto fail_parseAttributes
;
480 return SJME_ERROR_NOT_IMPLEMENTED
;
482 fail_parseAttributes
:
487 sjme_alloc_free(methods
);
489 result
->methods
= NULL
;
491 fail_readMethodCount
:
496 sjme_alloc_free(fields
);
498 result
->fields
= NULL
;
501 fail_allocInterfaceNames
:
502 if (interfaceNames
!= NULL
)
504 sjme_alloc_free(interfaceNames
);
505 interfaceNames
= NULL
;
506 result
->interfaceNames
= NULL
;
508 fail_readInterfaceCount
:
518 sjme_closeable_close(SJME_AS_CLOSEABLE(pool
));
530 sjme_closeable_close(SJME_AS_CLOSEABLE(result
));
531 return sjme_error_default(error
);
534 sjme_errorCode
sjme_class_parseAttributes(
535 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
536 sjme_attrInNotNull sjme_stream_input inStream
,
537 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
538 sjme_attrInNotNull sjme_stringPool inStringPool
,
539 sjme_attrInNotNull sjme_class_parseAttributeHandlerFunc handler
,
540 sjme_attrInNotNull sjme_pointer context
)
542 if (inPool
== NULL
|| inStream
== NULL
|| inConstPool
== NULL
||
543 inStringPool
== NULL
|| handler
== NULL
|| context
== NULL
)
544 return SJME_ERROR_NULL_ARGUMENTS
;
547 return SJME_ERROR_NOT_IMPLEMENTED
;
550 sjme_errorCode
sjme_class_parseConstantPool(
551 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
552 sjme_attrInNotNull sjme_stream_input inStream
,
553 sjme_attrInNotNull sjme_stringPool inStringPool
,
554 sjme_attrOutNotNull sjme_class_poolInfo
* outPool
)
556 sjme_errorCode error
;
560 sjme_list_sjme_class_poolEntry
* entries
;
561 sjme_class_poolEntry
* entry
;
562 sjme_class_poolEntry
* target
;
563 sjme_stringPool_string utf
;
564 sjme_class_poolInfo result
;
566 if (inPool
== NULL
|| inStream
== NULL
|| outPool
== NULL
||
567 inStringPool
== NULL
)
568 return SJME_ERROR_NULL_ARGUMENTS
;
570 /* Make sure we can actually allocate this. */
572 if (sjme_error_is(error
= sjme_alloc_weakNew(inPool
,
573 sizeof(*result
), NULL
, NULL
,
574 (sjme_pointer
*)&result
, NULL
)) || result
== NULL
)
575 goto fail_allocResult
;
578 if (sjme_error_is(error
= sjme_nvm_initCommon(
579 SJME_AS_NVM_COMMON(result
), SJME_NVM_STRUCT_POOL
)))
580 goto fail_initCommon
;
582 /* Read in pool count. */
584 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
585 inStream
, &count
)) || count
< 0)
588 /* Invalid pool size? */
589 if (count
< 0 || count
>= INT16_MAX
)
591 error
= SJME_ERROR_INVALID_CLASS_POOL_COUNT
;
595 /* Count up by one, since zero is included! */
598 /* Allocate resultant entries, where they will all go. */
600 if (sjme_error_is(error
= sjme_list_alloc(inPool
,
601 count
, &entries
, sjme_class_poolEntry
, 0)) || entries
== NULL
)
604 /* Read in all entries. */
605 /* This is a first pass since index items can refer to later entries. */
606 for (index
= 1; index
< count
- 1; index
++)
608 /* Which entry is being written? */
609 entry
= &entries
->elements
[index
];
613 if (sjme_error_is(error
= sjme_stream_inputReadValueJB(
614 inStream
, &tag
)) || tag
< 0)
618 sjme_message("TAG: %d", tag
);
623 /* Which tag is this? */
626 case SJME_CLASS_POOL_TYPE_DOUBLE
:
627 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
629 (sjme_jint
*)&entry
->constDouble
.value
.hi
)))
631 if (sjme_error_is(error
= sjme_stream_inputReadValueJI(
633 (sjme_jint
*)&entry
->constDouble
.value
.lo
)))
637 case SJME_CLASS_POOL_TYPE_CLASS
:
638 if (sjme_error_is(error
= sjme_stream_inputReadValueJS(
640 &entry
->classRef
.descriptorIndex
)))
645 case SJME_CLASS_POOL_TYPE_UTF
:
647 if (sjme_error_is(error
= sjme_stringPool_locateStream(
648 inStringPool
, inStream
, &utf
)) || utf
== NULL
)
652 sjme_message("Read UTF: %s",
655 /* Store and count up entry as we are using it now. */
656 entry
->utf
.utf
= utf
;
657 if (sjme_error_is(error
= sjme_alloc_weakRef(
663 sjme_todo("Impl? %d", tag
);
664 return SJME_ERROR_NOT_IMPLEMENTED
;
668 /* Second stage item linking. */
669 for (index
= 1; index
< count
- 1; index
++)
671 /* Which entry is being initialized? */
672 entry
= &entries
->elements
[index
];
674 /* Initialize accordingly. */
677 /* These are base elements that need no initialization. */
678 case SJME_CLASS_POOL_TYPE_UTF
:
679 case SJME_CLASS_POOL_TYPE_INTEGER
:
680 case SJME_CLASS_POOL_TYPE_FLOAT
:
681 case SJME_CLASS_POOL_TYPE_LONG
:
682 case SJME_CLASS_POOL_TYPE_DOUBLE
:
686 case SJME_CLASS_POOL_TYPE_CLASS
:
687 if (entry
->classRef
.descriptorIndex
<= 0 ||
688 entry
->classRef
.descriptorIndex
>= entries
->length
)
690 error
= SJME_ERROR_INVALID_CLASS_POOL_INDEX
;
694 /* Need to be a UTF string. */
695 target
= &entries
->elements
[entry
->classRef
.descriptorIndex
];
696 if (target
->type
!= SJME_CLASS_POOL_TYPE_UTF
)
698 error
= SJME_ERROR_WRONG_CLASS_POOL_INDEX_TYPE
;
702 /* Refer to it and count up, since we are using it. */
703 entry
->classRef
.descriptor
= target
->utf
.utf
;
704 if (sjme_error_is(error
= sjme_alloc_weakRef(
705 entry
->classRef
.descriptor
, NULL
)))
710 sjme_todo("Impl? %d", tag
);
711 return SJME_ERROR_NOT_IMPLEMENTED
;
716 result
->pool
= entries
;
720 return SJME_ERROR_NONE
;
727 sjme_alloc_free(entries
);
733 sjme_closeable_close(SJME_AS_CLOSEABLE(result
));
734 return sjme_error_default(error
);
737 sjme_errorCode
sjme_class_parseField(
738 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
739 sjme_attrInNotNull sjme_stream_input inStream
,
740 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
741 sjme_attrOutNotNull sjme_class_fieldInfo
* outField
)
743 if (inPool
== NULL
|| inStream
== NULL
|| inConstPool
== NULL
||
745 return SJME_ERROR_NULL_ARGUMENTS
;
748 return SJME_ERROR_NOT_IMPLEMENTED
;
751 sjme_errorCode
sjme_class_parseMethod(
752 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
753 sjme_attrInNotNull sjme_stream_input inStream
,
754 sjme_attrInNotNull sjme_class_poolInfo inConstPool
,
755 sjme_attrInOutNotNull sjme_class_methodInfo
* outMethod
)
757 sjme_errorCode error
;
758 sjme_class_methodInfo result
;
760 if (inPool
== NULL
|| inStream
== NULL
|| inConstPool
== NULL
||
762 return SJME_ERROR_NULL_ARGUMENTS
;
764 /* Ensure we can allocate the result first. */
766 if (sjme_error_is(error
= sjme_alloc_weakNew(inPool
,
767 sizeof(*result
), NULL
, NULL
,
768 (sjme_pointer
*)&result
, NULL
)) || result
== NULL
)
769 goto fail_allocResult
;
772 if (sjme_error_is(error
= sjme_nvm_initCommon(
773 SJME_AS_NVM_COMMON(result
),
774 SJME_NVM_STRUCT_METHOD_INFO
)))
775 goto fail_initResult
;
778 if (sjme_error_is(error
= sjme_class_methodFlagsParse(
779 inStream
, &result
->flags
)))
783 return SJME_ERROR_NOT_IMPLEMENTED
;
789 sjme_closeable_close(SJME_AS_CLOSEABLE(result
));
790 return sjme_error_default(error
);