/* -*- Mode: C; c-file-style: "gnu"; indent-tabs-mode:nil -*-
   jnifield.c -- Java Native Interface methods relating to object fields.
   Created: Chris Toshok <toshok@hungry.com>, 26-Jul-1997
 */
/*
  This file is part of Japhar, the GNU Virtual Machine for Java Bytecodes.
  Japhar is a project of The Hungry Programmers, GNU, and OryxSoft.

  Copyright (C) 1997, 1998, 1999 The Hungry Programmers

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "jniint.h"

jfieldID
JNIFUNC(GetFieldID)(JNIEnv *env,
                    jclass clazz,
                    const char *name,
                    const char *sig)
{
  HungryEnv *henv = JNIEnvToHEnv(env);
  FieldStruct *field = NULL;
  ClazzFile *cf = jclass_to_clazzfile(henv, clazz);
  int field_num;

  PR_ASSERT(NULL != env);
  PR_ASSERT(NULL != clazz);
  PR_ASSERT(NULL != cf);
  PR_ASSERT(NULL != name);
  PR_ASSERT(NULL != sig);

  for (field_num = 0; field_num < cf->num_fields; field_num++)
    {
      FieldStruct *cur_field = cf->fields[field_num];

      if (cur_field->access_flags & ACC_STATIC)
        continue;

      if (!PL_strcmp(cur_field->name, name)
          && !PL_strcmp(cur_field->sig_str, sig))
        {
          field = cur_field;
          break;
        }
    }
  
  if (field == NULL)
    {
      jclass no_such_field;

      (*env)->ExceptionClear(env);

      no_such_field = (*env)->FindClass(env, java_lang_NoSuchFieldException);
      if (no_such_field)
        (*env)->ThrowNew(env, no_such_field, name);
      else
        (*env)->FatalError(env, "Could not load java/lang/NoSuchFieldException");
      return NULL;
    }
  
  return field;
}

#define GETSET_FIELD(type, pretty_type, sig_type, union_element) \
type \
JNIFUNC(Get##pretty_type##Field)(JNIEnv *env, \
                                 jobject obj, \
                                 jfieldID fieldID) \
{ \
    HungryEnv *henv = JNIEnvToHEnv(env); \
    FieldStruct *field = (FieldStruct*)fieldID; \
    InterpValue val; \
        \
    if (HVM_ObjectIsReference(henv, obj)) \
        obj = HVM_ObjectGetReference(henv, obj); \
    HVM_FieldGet(obj, field, &val); \
        \
    return val.union_element; \
}  \
void \
JNIFUNC(Set##pretty_type##Field)(JNIEnv *env, \
                                 jobject obj, \
                                 jfieldID fieldID, \
                                 type value) \
{ \
    HungryEnv *henv = JNIEnvToHEnv(env); \
    FieldStruct *field = (FieldStruct*)fieldID; \
    InterpValue val; \
        \
    val.union_element = value; \
        \
    if (HVM_ObjectIsReference(henv, obj)) \
        obj = HVM_ObjectGetReference(henv, obj); \
    HVM_FieldSet(obj, field, val);  \
}


GETSET_FIELD(jboolean, Boolean, SIG_JBOOLEAN, z)
GETSET_FIELD(jbyte, Byte, SIG_JBYTE, b)
GETSET_FIELD(jchar, Char, SIG_JCHAR, c)
GETSET_FIELD(jshort, Short, SIG_JSHORT, s)
GETSET_FIELD(jint, Int, SIG_JINT, i)
GETSET_FIELD(jlong, Long, SIG_JLONG, j)
GETSET_FIELD(jfloat, Float, SIG_JFLOAT, f)
GETSET_FIELD(jdouble, Double, SIG_JDOUBLE, d)
GETSET_FIELD(jobject, Object, SIG_JOBJECT, l)
