/*
* Copyright (C) 2013-2015 RoboVM AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.robovm.apple.corefoundation;
import static org.robovm.rt.bro.MarshalerFlags.*;
/*<imports>*/
import java.io.*;
import java.nio.*;
import java.util.*;
import org.robovm.objc.*;
import org.robovm.objc.annotation.*;
import org.robovm.objc.block.*;
import org.robovm.rt.*;
import org.robovm.rt.annotation.*;
import org.robovm.rt.bro.*;
import org.robovm.rt.bro.annotation.*;
import org.robovm.rt.bro.ptr.*;
import org.robovm.apple.foundation.*;
import org.robovm.apple.dispatch.*;
import org.robovm.apple.coreservices.*;
import org.robovm.apple.coremedia.*;
import org.robovm.apple.uikit.*;
import org.robovm.apple.coretext.*;
/*</imports>*/
/*<javadoc>*/
/*</javadoc>*/
/*<annotations>*/@Library("CoreFoundation")/*</annotations>*/
@Marshalers({
@Marshaler(CFType.Marshaler.class),
@Marshaler(CFString.AsStringMarshaler.class)
})
/*<visibility>*/public/*</visibility>*/ class /*<name>*/CFType/*</name>*/
extends /*<extends>*/NativeObject/*</extends>*/
/*<implements>*//*</implements>*/ implements AutoCloseable {
/*<ptr>*/public static class CFTypePtr extends Ptr<CFType, CFTypePtr> {}/*</ptr>*/
public static class Marshaler {
@MarshalsPointer
public static CFType toObject(Class<? extends CFType> cls, long handle, long flags) {
return toObject(cls, handle, flags, true);
}
static CFType toObject(Class<? extends CFType> cls, long handle, long flags, boolean retain) {
if (handle == 0) {
return null;
}
long typeId = getTypeID(handle);
Class<? extends CFType> cfTypeClass = allCFTypeClasses.get(typeId);
if (cfTypeClass != null && cfTypeClass != cls) {
if (cls.isAssignableFrom(cfTypeClass)) {
/*
* Only use cfTypeClass if it's a subclass of the expected
* type (cls).
*/
cls = cfTypeClass;
}
}
CFType o = (CFType) NativeObject.Marshaler.toObject(cls, handle, flags);
if (retain) {
retain(handle);
}
return o;
}
@MarshalsPointer
public static long toNative(CFType o, long flags) {
if (o == null) {
return 0L;
}
if ((flags & (CALL_TYPE_CALLBACK | CALL_TYPE_GLOBAL_VALUE | CALL_TYPE_STRUCT_MEMBER)) > 0) {
// Make sure the object outlives the GC
o.retain();
}
return o.getHandle();
}
}
public static class AsListMarshaler {
@MarshalsPointer
public static List<?> toObject(Class<? extends CFType> cls, long handle, long flags) {
CFArray o = (CFArray) CFType.Marshaler.toObject(cls, handle, flags);
if (o == null) {
return null;
}
return o.toList(CFType.class);
}
@MarshalsPointer
public static long toNative(List<? extends CFType> l, long flags) {
if (l == null) {
return 0L;
}
CFArray o = null;
if (l instanceof CFArray) {
o = (CFArray) l;
} else {
o = CFArray.create((List<? extends CFType>) l);
}
return CFType.Marshaler.toNative(o, flags);
}
}
/**
* Marshaler used for create and copy methods which have already retained
* the object they return.
*/
public static class NoRetainMarshaler {
@MarshalsPointer
public static CFType toObject(Class<? extends CFType> cls, long handle, long flags) {
return Marshaler.toObject(cls, handle, flags, false);
}
@MarshalsPointer
public static long toNative(CFType o, long flags) {
return Marshaler.toNative(o, flags);
}
}
private static final LongMap<Class<? extends CFType>> allCFTypeClasses = new LongMap<>();
private static final int ABSTRACT = 0x00000400;
static {
@SuppressWarnings("unchecked")
Class<? extends CFType>[] classes = (Class<? extends CFType>[])
VM.listClasses(CFType.class, ClassLoader.getSystemClassLoader());
Class<?>[] emptyArgs = new Class<?>[0];
final Class<?> cfTypeClass = CFType.class;
for (Class<? extends CFType> cls : classes) {
if (cls != cfTypeClass && (cls.getModifiers() & ABSTRACT) == 0) {
try {
java.lang.reflect.Method m = cls.getDeclaredMethod("getClassTypeID", emptyArgs);
m.setAccessible(true);
Long typeId = (Long) m.invoke(null);
allCFTypeClasses.put(typeId, cls);
} catch (Throwable e) {
// Ignore, because several of Apple's CFType subclasses don't contain a getClassTypeID() method.
}
}
}
}
/*<bind>*/static { Bro.bind(CFType.class); }/*</bind>*/
/*<constants>*//*</constants>*/
/*<constructors>*/
protected CFType() {}
/*</constructors>*/
/*<properties>*//*</properties>*/
/*<members>*//*</members>*/
@Override
protected final void finalize() throws Throwable {
dispose(true);
}
public final void dispose() {
dispose(false);
}
protected void doDispose() {
// Only release once
long handle = getHandle();
if (handle != 0) {
release(handle);
}
}
protected void dispose(boolean finalizing) {
long handle = getHandle();
if (handle != 0) {
doDispose();
setHandle(0);
}
if (finalizing) {
try {
super.finalize();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
@Override
public final void close() {
try {
dispose(false);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
@Override
public String toString() {
try (CFString s = getDescription()) {
return s.toString();
}
}
@Bridge(symbol="CFGetTypeID")
private static native @MachineSizedUInt long getTypeID(@Pointer long handle);
@Bridge(symbol="CFRetain")
protected static native @Pointer long retain(@Pointer long handle);
@Bridge(symbol="CFRelease")
protected static native void release(@Pointer long handle);
/*<methods>*/
@Bridge(symbol="CFGetTypeID", optional=true)
public native @MachineSizedUInt long getTypeID();
@Bridge(symbol="CFCopyTypeIDDescription", optional=true)
public static native String getTypeIDDescription(@MachineSizedUInt long type_id);
@Bridge(symbol="CFRetain", optional=true)
public native CFType retain();
@Bridge(symbol="CFRelease", optional=true)
public native void release();
/**
* @since Available in iOS 7.0 and later.
*/
@Bridge(symbol="CFAutorelease", optional=true)
public native CFType autorelease();
@Bridge(symbol="CFGetRetainCount", optional=true)
public native @MachineSizedSInt long getRetainCount();
@Bridge(symbol="CFEqual", optional=true)
public native boolean equalsTo(CFType cf2);
@Bridge(symbol="CFHash", optional=true)
public native @MachineSizedUInt long hash();
@Bridge(symbol="CFCopyDescription", optional=true)
protected native @org.robovm.rt.bro.annotation.Marshaler(CFType.NoRetainMarshaler.class) CFString getDescription();
@Bridge(symbol="CFGetAllocator", optional=true)
public native CFAllocator getAllocator();
@Bridge(symbol="CFMakeCollectable", optional=true)
public native CFType makeCollectable();
@Bridge(symbol="CFShow", optional=true)
public native void show();
/*</methods>*/
}