Parse of method flags.
[SquirrelJME.git] / nanocoat / src / classy.c
blobb2131f224dbb272c6c6e5e232768b8bd9ef8deb2
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
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)
26 /** Public. */
27 #define SJME_CLASS_ACC_PUBLIC INT16_C(0x0001)
29 /** Private. */
30 #define SJME_CLASS_ACC_PRIVATE INT16_C(0x0002)
32 /** Protected. */
33 #define SJME_CLASS_ACC_PROTECTED INT16_C(0x0004)
35 /** Static member. */
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)
47 /** Bridge method. */
48 #define SJME_CLASS_ACC_BRIDGE INT16_C(0x0040)
50 /** Variable arguments. */
51 #define SJME_CLASS_ACC_VARARGS INT16_C(0x0080)
53 /** Native method. */
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;
87 sjme_todo("Impl?");
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)
95 sjme_errorCode error;
96 sjme_jshort rawFlags;
98 if (inStream == NULL || outFlags == NULL)
99 return SJME_ERROR_NULL_ARGUMENTS;
101 /* Read in flags. */
102 rawFlags = -1;
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;
134 /* Success! */
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;
146 sjme_jshort index;
147 sjme_class_poolEntry* result;
149 if (inStream == NULL || inClassPool == NULL || outEntry == NULL)
150 return SJME_ERROR_NULL_ARGUMENTS;
152 /* Read in index. */
153 index = -1;
154 if (sjme_error_is(error = sjme_stream_inputReadValueJS(
155 inStream, &index)))
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;
167 /* Success! */
168 *outEntry = result;
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;
185 sjme_todo("Impl?");
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;
202 sjme_todo("Impl?");
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;
216 /* Read in flags. */
217 rawFlags = -1;
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;
259 /* Success! */
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 ||
283 outClass == NULL)
284 return SJME_ERROR_NONE;
286 /* Make sure we can actually allocate the resultant class. */
287 result = NULL;
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;
293 /* Initialize. */
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. */
300 magic = INT32_MAX;
301 if (sjme_error_is(error = sjme_stream_inputReadValueJI(
302 inStream, &magic)))
303 goto fail_readMagic;
305 /* It must be valid! */
306 if (magic != SJME_CLASS_MAGIC)
308 error = SJME_ERROR_INVALID_CLASS_MAGIC;
309 goto fail_badMagic;
312 /* Read in version info. */
313 minor = INT16_MAX;
314 if (sjme_error_is(error = sjme_stream_inputReadValueJS(
315 inStream, &minor)))
316 goto fail_readMinor;
318 major = INT16_MAX;
319 if (sjme_error_is(error = sjme_stream_inputReadValueJS(
320 inStream, &major)))
321 goto fail_readMajor;
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;
335 /* Not valid. */
336 else
338 error = SJME_ERROR_INVALID_CLASS_VERSION;
339 goto fail_badVersion;
342 /* Set version. */
343 result->version = actualVersion;
345 /* Parse the constant pool. */
346 pool = NULL;
347 if (sjme_error_is(error = sjme_class_parseConstantPool(
348 inPool, inStream, inStringPool, &pool)) || pool == NULL)
349 goto fail_parsePool;
351 /* We are using this, so count it up. */
352 if (sjme_error_is(error = sjme_alloc_weakRef(pool, NULL)))
353 goto fail_countPool;
354 result->pool = pool;
356 /* Read in flags. */
357 if (sjme_error_is(error = sjme_class_classFlagsParse(
358 inStream, &result->flags)))
359 goto fail_readFlags;
361 /* Read in this name. */
362 thisName = NULL;
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;
369 /* Reference it. */
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. */
376 superName = NULL;
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? */
393 interfaceCount = -1;
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++)
409 /* Read in name. */
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;
418 /* Reference it. */
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. */
426 fieldCount = -1;
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. */
432 fields = NULL;
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. */
450 methodCount = -1;
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. */
456 methods = NULL;
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;
479 sjme_todo("Impl?");
480 return SJME_ERROR_NOT_IMPLEMENTED;
482 fail_parseAttributes:
483 fail_parseMethod:
484 fail_allocMethods:
485 if (methods != NULL)
487 sjme_alloc_free(methods);
488 methods = NULL;
489 result->methods = NULL;
491 fail_readMethodCount:
492 fail_parseField:
493 fail_allocFields:
494 if (fields != NULL)
496 sjme_alloc_free(fields);
497 fields = NULL;
498 result->fields = NULL;
500 fail_readFieldCount:
501 fail_allocInterfaceNames:
502 if (interfaceNames != NULL)
504 sjme_alloc_free(interfaceNames);
505 interfaceNames = NULL;
506 result->interfaceNames = NULL;
508 fail_readInterfaceCount:
509 fail_refSuperName:
510 fail_readSuperName:
511 fail_refThisName:
512 fail_readThisName:
513 fail_readFlags:
514 fail_countPool:
515 fail_parsePool:
516 if (pool != NULL)
518 sjme_closeable_close(SJME_AS_CLOSEABLE(pool));
519 pool = NULL;
520 result->pool = NULL;
522 fail_badVersion:
523 fail_readMinor:
524 fail_readMajor:
525 fail_badMagic:
526 fail_readMagic:
527 fail_initResult:
528 fail_allocResult:
529 if (result != NULL)
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;
546 sjme_todo("Impl?");
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;
557 sjme_jshort count;
558 sjme_jint index;
559 sjme_jbyte tag;
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. */
571 result = NULL;
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;
577 /* Initialize it. */
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. */
583 count = -1;
584 if (sjme_error_is(error = sjme_stream_inputReadValueJS(
585 inStream, &count)) || count < 0)
586 goto fail_readCount;
588 /* Invalid pool size? */
589 if (count < 0 || count >= INT16_MAX)
591 error = SJME_ERROR_INVALID_CLASS_POOL_COUNT;
592 goto fail_poolCount;
595 /* Count up by one, since zero is included! */
596 count += 1;
598 /* Allocate resultant entries, where they will all go. */
599 entries = NULL;
600 if (sjme_error_is(error = sjme_list_alloc(inPool,
601 count, &entries, sjme_class_poolEntry, 0)) || entries == NULL)
602 goto fail_entryList;
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];
611 /* Read in tag. */
612 tag = -1;
613 if (sjme_error_is(error = sjme_stream_inputReadValueJB(
614 inStream, &tag)) || tag < 0)
615 goto fail_readTag;
617 /* Debug. */
618 sjme_message("TAG: %d", tag);
620 /* Set tag. */
621 entry->type = tag;
623 /* Which tag is this? */
624 switch (tag)
626 case SJME_CLASS_POOL_TYPE_DOUBLE:
627 if (sjme_error_is(error = sjme_stream_inputReadValueJI(
628 inStream,
629 (sjme_jint*)&entry->constDouble.value.hi)))
630 goto fail_readItem;
631 if (sjme_error_is(error = sjme_stream_inputReadValueJI(
632 inStream,
633 (sjme_jint*)&entry->constDouble.value.lo)))
634 goto fail_readItem;
635 break;
637 case SJME_CLASS_POOL_TYPE_CLASS:
638 if (sjme_error_is(error = sjme_stream_inputReadValueJS(
639 inStream,
640 &entry->classRef.descriptorIndex)))
641 goto fail_readItem;
642 break;
644 /* UTF String. */
645 case SJME_CLASS_POOL_TYPE_UTF:
646 utf = NULL;
647 if (sjme_error_is(error = sjme_stringPool_locateStream(
648 inStringPool, inStream, &utf)) || utf == NULL)
649 goto fail_readItem;
651 /* Debug. */
652 sjme_message("Read UTF: %s",
653 utf->chars);
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(
658 utf, NULL)))
659 goto fail_readItem;
660 break;
662 default:
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. */
675 switch (entry->type)
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:
683 break;
685 /* Class type. */
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;
691 goto fail_initItem;
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;
699 goto fail_initItem;
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)))
706 goto fail_initItem;
707 break;
709 default:
710 sjme_todo("Impl? %d", tag);
711 return SJME_ERROR_NOT_IMPLEMENTED;
715 /* Setup details. */
716 result->pool = entries;
718 /* Success! */
719 *outPool = result;
720 return SJME_ERROR_NONE;
722 fail_initItem:
723 fail_readItem:
724 fail_readTag:
725 fail_entryList:
726 if (entries != NULL)
727 sjme_alloc_free(entries);
728 fail_poolCount:
729 fail_readCount:
730 fail_initCommon:
731 fail_allocResult:
732 if (result != NULL)
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 ||
744 outField == NULL)
745 return SJME_ERROR_NULL_ARGUMENTS;
747 sjme_todo("Impl?");
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 ||
761 outMethod == NULL)
762 return SJME_ERROR_NULL_ARGUMENTS;
764 /* Ensure we can allocate the result first. */
765 result = NULL;
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;
771 /* Initialize it. */
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;
777 /* Read in flags. */
778 if (sjme_error_is(error = sjme_class_methodFlagsParse(
779 inStream, &result->flags)))
780 goto fail_readFlags;
782 sjme_todo("Impl?");
783 return SJME_ERROR_NOT_IMPLEMENTED;
785 fail_readFlags:
786 fail_initResult:
787 fail_allocResult:
788 if (result != NULL)
789 sjme_closeable_close(SJME_AS_CLOSEABLE(result));
790 return sjme_error_default(error);