/*
 * java.lang.reflect.Field.c
 *
 * Copyright (c) 1996,97 T. J. Wilkinson & Associates, London, UK.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Written by Tim Wilkinson <tim@tjwassoc.co.uk>
 */

#include "config.h"
#include "config-std.h"
#include "config-mem.h"
#include "../../../../kaffe/kaffevm/gtypes.h"
#include "../../../../kaffe/kaffevm/access.h"
#include "../../../../kaffe/kaffevm/constants.h"
#include "../../../../kaffe/kaffevm/object.h"
#include "../../../../kaffe/kaffevm/classMethod.h"
#include "../../../../kaffe/kaffevm/itypes.h"
#include "../../../../kaffe/kaffevm/support.h"
#include "../../../../kaffe/kaffevm/soft.h"
#include "java.io.stubs/InputStream.h"
#include "java.io.stubs/PrintStream.h"
#include "java.lang.stubs/System.h"
#include "java.lang.reflect.stubs/Field.h"
#include <native.h>
#include "defs.h"

static
char*
getFieldAddress(Hjava_lang_reflect_Field* this, struct Hjava_lang_Object* obj)
{
	Hjava_lang_Class* clas;
	Field* fld;

	clas = (Hjava_lang_Class*)unhand(this)->clazz;
	fld = CLASS_FIELDS(clas) + unhand(this)->slot;

	if (unhand(this)->slot < CLASS_NSFIELDS(clas)) {
		return (FIELD_ADDRESS(fld));
	}
	else {
		if (obj == NULL) {
			SignalError(0, "java.lang.NullPointerException", "");
		}
		if  (!soft_instanceof(fld->type, obj)) {
			SignalError(0,"java.lang.IllegalArgumentException","");
		}
		return (((char*)(obj+1)) + FIELD_OFFSET(fld));
	}
}

struct Hjava_lang_Object*
java_lang_reflect_Field_get(Hjava_lang_reflect_Field* this, struct Hjava_lang_Object* obj)
{
	Hjava_lang_Class* clas;
	Field* fld;
	char* base;

	clas = (Hjava_lang_Class*) unhand(this)->clazz;
	fld = CLASS_FIELDS(clas) + unhand(this)->slot;
	base = getFieldAddress(this, obj);
	if (CLASS_IS_PRIMITIVE(fld->type)) {  /* FIXME */
		unimp("Field.get not implemented for primitive fields");
	}
	return (*(struct Hjava_lang_Object**)base);
}

void
java_lang_reflect_Field_set(Hjava_lang_reflect_Field* this, struct Hjava_lang_Object* obj, struct Hjava_lang_Object* value)
{
	Hjava_lang_Class* clas;
	Field* fld;
	char* base;

	clas = (Hjava_lang_Class*) unhand(this)->clazz;
	fld = CLASS_FIELDS(clas) + unhand(this)->slot;
	base = getFieldAddress(this, obj);
	if (CLASS_IS_PRIMITIVE(fld->type)) {  /* FIXME */
		unimp("Field.set not implemented for primitive fields");
	}
	if (fld->accflags & ACC_FINAL) {
		SignalError(0,"java.lang.IllegalAccessException", "");
	}
	if (value != NULL && ! soft_instanceof(fld->type, value)) {
		SignalError(0,"java.lang.IllegalArgumentException", "");
	}
	*(struct Hjava_lang_Object**)base = value;
}
