alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (Coder.java)

This example Java source code file (Coder.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

class, coder, idcoder, inst, jobjcruntime, nativeargumentbuffer, nsclasscoder, override, reflection, runtimeexception, selcoder, string, struct, unknowncoder, voidcoder

The Coder.java Java example source code

/*
 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.apple.jobjc;

import java.io.StringWriter;
import java.lang.reflect.Method;

import com.apple.jobjc.JObjCRuntime.Width;
import com.apple.jobjc.PrimitiveCoder.BoolCoder;
import com.apple.jobjc.PrimitiveCoder.DoubleCoder;
import com.apple.jobjc.PrimitiveCoder.FloatCoder;
import com.apple.jobjc.PrimitiveCoder.SCharCoder;
import com.apple.jobjc.PrimitiveCoder.SIntCoder;
import com.apple.jobjc.PrimitiveCoder.SLongLongCoder;
import com.apple.jobjc.PrimitiveCoder.SShortCoder;

public abstract class Coder<T> {
    private static native long getNativeFFITypePtrForCode(final int code);

    static final int FFI_VOID        = 0;
    static final int FFI_PTR        = FFI_VOID+1;

    static final int FFI_SINT8        = FFI_PTR+1;
    static final int FFI_UINT8        = FFI_SINT8+1;
    static final int FFI_SINT16        = FFI_UINT8+1;
    static final int FFI_UINT16        = FFI_SINT16+1;
    static final int FFI_SINT32        = FFI_UINT16+1;
    static final int FFI_UINT32        = FFI_SINT32+1;
    static final int FFI_SINT64        = FFI_UINT32+1;
    static final int FFI_UINT64        = FFI_SINT64+1;

    static final int FFI_FLOAT        = FFI_UINT64+1;
    static final int FFI_DOUBLE        = FFI_FLOAT+1;
    static final int FFI_LONGDOUBLE    = FFI_DOUBLE+1;

    private static long[] ffiCodesToFFITypePtrs;
    static{
        System.loadLibrary("JObjC");
        ffiCodesToFFITypePtrs = new long[FFI_LONGDOUBLE + 1];
        for (int i = 0; i < FFI_LONGDOUBLE + 1; i++) ffiCodesToFFITypePtrs[i] = getNativeFFITypePtrForCode(i);
    }

    long getFFITypePtr() {
        return ffiCodesToFFITypePtrs[getTypeCode()];
    }

    // runtime coding
    public abstract void push(final JObjCRuntime runtime, final long addr, final T x);
    public abstract T pop(final JObjCRuntime runtime, final long addr);

    public void push(final NativeArgumentBuffer args, final T x){
        push(args.runtime, args.argValuesPtr, x);
        args.didPutArgValue(sizeof());
    }

    public T pop(final NativeArgumentBuffer args){
        return pop(args.runtime, args.retValPtr);
    }

    public abstract int sizeof(Width w);
    final public int sizeof(){ return sizeof(JObjCRuntime.WIDTH); }

    //

    public Coder(int ffiTypeCode, String objCEncoding, Class jclass, Class jprim) {
        this.ffiTypeCode = ffiTypeCode;
        this.objCEncoding = objCEncoding;
        this.jclass = jclass;
        this.jprim = jprim;
    }

    public Coder(int ffiTypeCode, String objCEncoding, Class jclass) {
        this(ffiTypeCode, objCEncoding, jclass, null);
    }

    private final int ffiTypeCode;
    private final String objCEncoding;
    private final Class jclass;
    private final Class jprim;

    final int getTypeCode() { return ffiTypeCode; }
    final String getObjCEncoding(){ return objCEncoding; }
    public final Class getJavaClass() { return jclass; }
    public final Class getJavaPrimitive() { return jprim; }

    // runtime coding

    private static Coder[] runtimeCoders;
    static public Coder getCoderAtRuntimeForType(Class cls){
        if(runtimeCoders == null) runtimeCoders = new Coder[]{
            NSClassCoder.INST, IDCoder.INST, PointerCoder.INST,
            DoubleCoder.INST, FloatCoder.INST, SLongLongCoder.INST,
            SIntCoder.INST, SShortCoder.INST, SCharCoder.INST, BoolCoder.INST,
            VoidCoder.INST
        };

        for(Coder c : runtimeCoders)
            if((c.getJavaClass() != null && c.getJavaClass().isAssignableFrom(cls)) ||
                    (c.getJavaPrimitive() != null && c.getJavaPrimitive().isAssignableFrom(cls)))
                return c;

        if(Struct.class.isAssignableFrom(cls)){
            try {
                Method m = cls.getDeclaredMethod("getStructCoder");
                m.setAccessible(true);
                return (Coder) m.invoke(null);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        throw new RuntimeException("Could not find suitable coder for " + cls);
    }

    static public Coder getCoderAtRuntime(Object inst){
        if(inst == null)              return PointerCoder.INST;
        if(inst instanceof Struct)    return ((Struct) inst).getCoder();
        return getCoderAtRuntimeForType(inst.getClass());
    }

    //

    public static final class VoidCoder extends Coder<Object>{
        public static final VoidCoder INST = new VoidCoder();
        public VoidCoder(){ super(FFI_VOID, "v", Void.class, void.class); }
        @Override public int sizeof(Width w) { return -1; }
        @Override public Object pop(JObjCRuntime runtime, long addr) { throw new RuntimeException("Trying to pop a Void."); }
        @Override public void push(JObjCRuntime runtime, long addr, Object x) { throw new RuntimeException("Trying to push a Void."); }
    }

    public static final class UnknownCoder extends Coder<Object> {
        public static final UnknownCoder INST = new UnknownCoder();
        public UnknownCoder(){ super(-1, "?", null, null); }
        @Override public int sizeof(Width w) { return -1; }
        @Override public void push(JObjCRuntime runtime, long addr, Object x) { throw new RuntimeException("Coder not implemented");}
        @Override public Object pop(JObjCRuntime runtime, long addr) { throw new RuntimeException("Coder not implemented"); }
    }

    public static final class PrimitivePointerCoder extends Coder<Long> {
        public static final PrimitivePointerCoder INST = new PrimitivePointerCoder();
        public PrimitivePointerCoder(){ super(Coder.FFI_PTR, "^?", Long.class, long.class); }
        @Override public int sizeof(Width w) { return JObjCRuntime.PTR_LEN; }

        public void push(JObjCRuntime runtime, long addr, long x) {
            if(JObjCRuntime.IS64)
                runtime.unsafe.putLong(addr, x);
            else
                runtime.unsafe.putInt(addr, (int) x);
        }

        public void push(final JObjCRuntime runtime, final NativeArgumentBuffer argBuf, final long ptr) {
            push(runtime, argBuf.argValuesPtr, ptr);
            argBuf.didPutArgValue(sizeof());
        }

        public long popPtr(final JObjCRuntime runtime, final long addr) {
            return JObjCRuntime.IS64 ? runtime.unsafe.getLong(addr) : runtime.unsafe.getInt(addr);
        }

        public long popPtr(final JObjCRuntime runtime, final NativeArgumentBuffer argBuf) {
            return popPtr(runtime, argBuf.retValPtr);
        }

        @Override public Long pop(JObjCRuntime runtime, long addr) { return popPtr(runtime, addr); }
        @Override public void push(JObjCRuntime runtime, long addr, Long x) { push(runtime, addr, (long) x); }
    }

    public static final class PointerCoder extends Coder<Pointer> {
        public static final PointerCoder INST = new PointerCoder();
        public PointerCoder(){ super(FFI_PTR, "^?", Pointer.class); }
        @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }

        @Override public Pointer pop(JObjCRuntime runtime, long addr) {
            return new Pointer(PrimitivePointerCoder.INST.popPtr(runtime, addr));
        }
        @Override public void push(JObjCRuntime runtime, long addr, Pointer x) {
            PrimitivePointerCoder.INST.push(runtime, addr, x == null ? 0 : x.ptr);
        }
    }

    public static final class SELCoder extends Coder<SEL> {
        public static final SELCoder INST = new SELCoder();
        public SELCoder(){ super(FFI_PTR, ":", SEL.class); }
        @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }

        @Override public void push(JObjCRuntime runtime, long addr, SEL x) {
            PrimitivePointerCoder.INST.push(runtime, addr, x == null ? 0 : x.selPtr);
        }
        @Override public SEL pop(JObjCRuntime runtime, long addr) {
            return new SEL(PrimitivePointerCoder.INST.popPtr(runtime, addr));
        }
    }

    public static abstract class StructCoder extends Coder<Struct> {
        private final FFIType ffiType;
        final int sizeof;

        public StructCoder(final int sizeof, final Coder... elementCoders){
            super(-1, objCEncoding(elementCoders), null);
            this.ffiType = new FFIType(elementCoders);
            this.sizeof = sizeof;
        }

        @Override public int sizeof(Width w) { return sizeof; }

        private static String objCEncoding(final Coder[] elementCoders) {
            StringWriter str = new StringWriter();
            str.append("{?=");
            for(Coder c : elementCoders)
                str.append(c.getObjCEncoding());
            str.append("}");
            return str.toString();
        }

        @Override long getFFITypePtr() { return ffiType.getPtr(); }

        @Override public void push(NativeArgumentBuffer argBuf, Struct x) {
            // Just point to the instance on the heap instead of copying it onto the arg buf.
            argBuf.doPutArgPtr(x.raw.bufferPtr);
        }

        @Override public void push(JObjCRuntime rt, long addr, Struct x) {
            rt.unsafe.copyMemory(x.raw.bufferPtr, addr, sizeof);
        }

        protected abstract Struct newInstance(JObjCRuntime runtime);

        @Override public Struct pop(final JObjCRuntime runtime, final long addr) {
            Struct s = newInstance(runtime);
            runtime.unsafe.copyMemory(addr, s.raw.bufferPtr, sizeof);
            return s;
        }
    }

    public static final class IDCoder extends Coder<ID>{
        public static final IDCoder INST = new IDCoder();
        public IDCoder(){ super(FFI_PTR, "@", ID.class); }
        @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }

        public <T extends ID> T newID(final JObjCRuntime runtime, final long objPtr) {
            return (T) ID.getObjCObjectFor(runtime, objPtr);
        }

        @Override public ID pop(final JObjCRuntime runtime, final long addr) {
            return newID(runtime, PrimitivePointerCoder.INST.popPtr(runtime, addr));
        }

        @Override public void push(final JObjCRuntime runtime, final long addr, final ID x) {
            PointerCoder.INST.push(runtime, addr, x);
        }
    }

    public static final class NSClassCoder extends Coder<NSClass>{
        public static final NSClassCoder INST = new NSClassCoder();
        public NSClassCoder(){ super(FFI_PTR, "#", NSClass.class); }
        @Override public int sizeof(Width w) { return PrimitivePointerCoder.INST.sizeof(w); }

        @Override public NSClass pop(JObjCRuntime runtime, long addr) {
            final long clsPtr = PrimitivePointerCoder.INST.popPtr(runtime, addr);
            if (clsPtr == 0) return null;
            return NSClass.getObjCClassFor(runtime, clsPtr);
        }
        @Override public void push(JObjCRuntime runtime, long addr, NSClass x) {
            PointerCoder.INST.push(runtime, addr, x);
        }
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java Coder.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.