Merge pull request #12 from readdle/dev/fix-local-ref-issues
Fix local ref issues
This commit is contained in:
commit
1758dcd711
|
@ -124,7 +124,7 @@ public extension JNICore {
|
|||
public func `throw`() {
|
||||
switch self {
|
||||
case .classNotFoundException(let message):
|
||||
assert(JNI.api.ThrowNew(JNI.env, ExceptionClass, "ClassNotFoundaException: \(message)") == 0)
|
||||
assert(JNI.api.ThrowNew(JNI.env, ExceptionClass, "ClassNotFoundException: \(message)") == 0)
|
||||
case .methodNotFoundException(let message):
|
||||
assert(JNI.api.ThrowNew(JNI.env, ExceptionClass, "MethodNotFoundException: \(message)") == 0)
|
||||
case .fieldNotFoundException(let message):
|
||||
|
@ -136,7 +136,7 @@ public extension JNICore {
|
|||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .classNotFoundException(let message):
|
||||
return "ClassNotFoundaException: \(message)"
|
||||
return "ClassNotFoundException: \(message)"
|
||||
case .methodNotFoundException(let message):
|
||||
return "MethodNotFoundException: \(message)"
|
||||
case .fieldNotFoundException(let message):
|
||||
|
|
|
@ -47,15 +47,15 @@ public extension JNIObject {
|
|||
|
||||
func callStringMethod(method: String? = nil, functionName: String = #function, _ args: JNIArgumentProtocol...) -> String {
|
||||
let methodName = method ?? String(functionName.split(separator: "(")[0])
|
||||
return String(javaObject: self.internalcallObjectMethod(method: methodName, returnType: "Ljava/lang/String;", args))
|
||||
return String(javaObject: self.internalCallObjectMethod(method: methodName, returnType: "Ljava/lang/String;", args))
|
||||
}
|
||||
|
||||
func callObjectMethod(method: String? = nil, functionName: String = #function, returnType: String, _ args: JNIArgumentProtocol...) -> jobject? {
|
||||
let methodName = method ?? String(functionName.split(separator: "(")[0])
|
||||
return self.internalcallObjectMethod(method: methodName, returnType: returnType, args)
|
||||
return self.internalCallObjectMethod(method: methodName, returnType: returnType, args)
|
||||
}
|
||||
|
||||
private func internalcallObjectMethod(method: String, returnType: String, _ args: [JNIArgumentProtocol]) -> jobject? {
|
||||
private func internalCallObjectMethod(method: String, returnType: String, _ args: [JNIArgumentProtocol]) -> jobject? {
|
||||
let sig = "(\(args.map({ $0.sig() }).joined()))\(returnType)"
|
||||
let methodID = try! JNI.getJavaMethod(forClass: self.className, method: method, sig: sig)
|
||||
return checkArgumentAndWrap(args: args, { argsPtr in
|
||||
|
|
|
@ -94,17 +94,16 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedDecodingContainerPro
|
|||
|
||||
let decoder: JavaDecoder
|
||||
let jniStorage: JNIStorageObject
|
||||
let javaObject: jobject
|
||||
let javaClass: String
|
||||
|
||||
fileprivate init(decoder: JavaDecoder, jniStorage: JNIStorageObject) {
|
||||
self.decoder = decoder
|
||||
self.jniStorage = jniStorage
|
||||
self.javaObject = jniStorage.javaObject
|
||||
self.codingPath = jniStorage.codingPath
|
||||
|
||||
codingPath = jniStorage.codingPath
|
||||
switch jniStorage.type {
|
||||
case let .object(className):
|
||||
self.javaClass = className
|
||||
javaClass = className
|
||||
default:
|
||||
fatalError("Wrong container type")
|
||||
}
|
||||
|
@ -136,21 +135,37 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedDecodingContainerPro
|
|||
// MARK: Decode JNI primitive fields
|
||||
private func decodeBoolean(forKey key: String) throws -> Bool {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "Z")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
return JNI.api.GetBooleanField(JNI.env, javaObject, fieldID) == JNI_TRUE
|
||||
}
|
||||
|
||||
private func decodeByte(forKey key: String) throws -> Int8 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "B")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
return JNI.api.GetByteField(JNI.env, javaObject, fieldID)
|
||||
}
|
||||
|
||||
private func decodeShort(forKey key: String) throws -> Int16 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "S")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
return JNI.api.GetShortField(JNI.env, javaObject, fieldID)
|
||||
}
|
||||
|
||||
private func decodeInteger(forKey key: String) throws -> Int32 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "I")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
#if arch(x86_64) || arch(arm64)
|
||||
return JNI.api.GetIntField(JNI.env, javaObject, fieldID)
|
||||
#else
|
||||
|
@ -160,16 +175,28 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedDecodingContainerPro
|
|||
|
||||
private func decodeLong(forKey key: String) throws -> Int64 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "J")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
return JNI.api.GetLongField(JNI.env, javaObject, fieldID)
|
||||
}
|
||||
|
||||
private func decodeFloat(forKey key: String) throws -> Float {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "F")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
return JNI.api.GetFloatField(JNI.env, javaObject, fieldID)
|
||||
}
|
||||
|
||||
private func decodeDouble(forKey key: String) throws -> Double {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "D")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
return JNI.api.GetDoubleField(JNI.env, javaObject, fieldID)
|
||||
}
|
||||
|
||||
|
@ -302,7 +329,10 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedDecodingContainerPro
|
|||
let classname: String
|
||||
if type == AnyCodable.self {
|
||||
var locals = [jobject]()
|
||||
let javaObject = jniStorage.javaObject
|
||||
let cls = JNI.api.GetObjectClass(JNI.env, javaObject)!
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
|
||||
let javaTypename = key.stringValue.localJavaObject(&locals)
|
||||
guard let field = JNI.CallObjectMethod(cls, ClassGetFieldMethod, javaTypename!) else {
|
||||
JNI.ExceptionReset()
|
||||
|
@ -324,6 +354,10 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedDecodingContainerPro
|
|||
}
|
||||
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key.stringValue, sig: "L\(classname);")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.api.DeleteLocalRef(JNI.env, javaObject)
|
||||
}
|
||||
guard let object = JNI.api.GetObjectField(JNI.env, javaObject, fieldID) else {
|
||||
return nil
|
||||
}
|
||||
|
@ -360,18 +394,18 @@ fileprivate class JavaHashMapKeyedContainer<K : CodingKey>: KeyedDecodingContain
|
|||
|
||||
private let decoder: JavaDecoder
|
||||
private let jniStorage: JNIStorageObject
|
||||
private let javaObject: jobject
|
||||
|
||||
private var javaKeys = [AnyHashable: jobject]()
|
||||
|
||||
fileprivate init(decoder: JavaDecoder, jniStorage: JNIStorageObject) throws {
|
||||
self.decoder = decoder
|
||||
self.jniStorage = jniStorage
|
||||
self.javaObject = jniStorage.javaObject
|
||||
self.codingPath = jniStorage.codingPath
|
||||
|
||||
codingPath = jniStorage.codingPath
|
||||
|
||||
let javaObject = jniStorage.javaObject
|
||||
let keySet = JNI.api.CallObjectMethodA(JNI.env, javaObject, HashMapKeySetMethod, nil)
|
||||
let keyArray = JNI.api.CallObjectMethodA(JNI.env, keySet, SetToArrayMethod, nil)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
defer {
|
||||
JNI.DeleteLocalRef(keySet)
|
||||
JNI.DeleteLocalRef(keyArray)
|
||||
|
@ -436,7 +470,11 @@ fileprivate class JavaHashMapKeyedContainer<K : CodingKey>: KeyedDecodingContain
|
|||
}
|
||||
|
||||
let javaKey = javaKeys[typeKey]
|
||||
guard let object = JNI.CallObjectMethod(self.javaObject, methodID: HashMapGetMethod, args: [jvalue(l: javaKey)]) else {
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
guard let object = JNI.CallObjectMethod(javaObject!, methodID: HashMapGetMethod, args: [jvalue(l: javaKey)]) else {
|
||||
throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Can't find object")
|
||||
}
|
||||
defer {
|
||||
|
@ -480,7 +518,6 @@ fileprivate class JavaHashMapUnkeyedContainer: UnkeyedDecodingContainer {
|
|||
|
||||
let decoder: JavaDecoder
|
||||
let jniStorage: JNIStorageObject
|
||||
let javaObject: jobject
|
||||
|
||||
private var javaKeys: jarray
|
||||
private var javaCurrentKey: jobject?
|
||||
|
@ -488,15 +525,14 @@ fileprivate class JavaHashMapUnkeyedContainer: UnkeyedDecodingContainer {
|
|||
fileprivate init(decoder: JavaDecoder, jniStorage: JNIStorageObject) throws {
|
||||
self.decoder = decoder
|
||||
self.jniStorage = jniStorage
|
||||
self.javaObject = jniStorage.javaObject
|
||||
self.codingPath = jniStorage.codingPath
|
||||
self.count = Int(JNI.CallIntMethod(self.javaObject, methodID: HashMapSizeMethod)) * 2
|
||||
|
||||
codingPath = jniStorage.codingPath
|
||||
|
||||
let javaObject = jniStorage.javaObject
|
||||
count = Int(JNI.CallIntMethod(javaObject!, methodID: HashMapSizeMethod)) * 2
|
||||
let keySet = JNI.api.CallObjectMethodA(JNI.env, javaObject, HashMapKeySetMethod, nil)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
javaKeys = JNI.api.CallObjectMethodA(JNI.env, keySet, SetToArrayMethod, nil)!
|
||||
defer {
|
||||
JNI.api.DeleteLocalRef(JNI.env, keySet)
|
||||
}
|
||||
JNI.DeleteLocalRef(keySet)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
@ -510,7 +546,11 @@ fileprivate class JavaHashMapUnkeyedContainer: UnkeyedDecodingContainer {
|
|||
func decode<T>(_ type: T.Type) throws -> T where T : Decodable {
|
||||
let codingKey = JavaKey(intValue: currentIndex)
|
||||
if let javaCurrentKey = javaCurrentKey {
|
||||
guard let object = JNI.CallObjectMethod(self.javaObject, methodID: HashMapGetMethod, args: [jvalue(l: javaCurrentKey)]) else {
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
guard let object = JNI.CallObjectMethod(javaObject!, methodID: HashMapGetMethod, args: [jvalue(l: javaCurrentKey)]) else {
|
||||
throw DecodingError.dataCorruptedError(in: self, debugDescription: "Can't find object")
|
||||
}
|
||||
currentIndex += 1
|
||||
|
@ -568,8 +608,10 @@ fileprivate class JavaArrayContainer: UnkeyedDecodingContainer {
|
|||
self.decoder = decoder
|
||||
self.jniStorage = jniStorage
|
||||
self.codingPath = jniStorage.codingPath
|
||||
self.count = Int(JNI.CallIntMethod(jniStorage.javaObject, methodID: CollectionSizeMethod))
|
||||
self.javaIterator = JNI.CallObjectMethod(jniStorage.javaObject, methodID: CollectionIteratorMethod)!
|
||||
let javaObject = jniStorage.javaObject
|
||||
self.count = Int(JNI.CallIntMethod(javaObject!, methodID: CollectionSizeMethod))
|
||||
self.javaIterator = JNI.CallObjectMethod(javaObject!, methodID: CollectionIteratorMethod)!
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
@ -610,17 +652,16 @@ fileprivate class JavaEnumContainer: SingleValueDecodingContainer {
|
|||
|
||||
let decoder: JavaDecoder
|
||||
let jniStorage: JNIStorageObject
|
||||
let javaObject: jobject
|
||||
let javaClass: String
|
||||
|
||||
fileprivate init(decoder: JavaDecoder, jniStorage: JNIStorageObject) {
|
||||
self.decoder = decoder
|
||||
self.jniStorage = jniStorage
|
||||
self.javaObject = jniStorage.javaObject
|
||||
self.codingPath = jniStorage.codingPath
|
||||
|
||||
codingPath = jniStorage.codingPath
|
||||
switch jniStorage.type {
|
||||
case let .object(className):
|
||||
self.javaClass = className
|
||||
javaClass = className
|
||||
default:
|
||||
fatalError("Wrong container type")
|
||||
}
|
||||
|
@ -632,67 +673,91 @@ fileprivate class JavaEnumContainer: SingleValueDecodingContainer {
|
|||
|
||||
func decode(_ type: Int.Type) throws -> Int {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "I")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetIntField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return Int(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: Int8.Type) throws -> Int8 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "B")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetByteField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return Int8(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: Int16.Type) throws -> Int16 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "S")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetShortField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return Int16(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: Int32.Type) throws -> Int32 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "I")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetIntField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return Int32(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: Int64.Type) throws -> Int64 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "J")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetLongField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return Int64(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: UInt.Type) throws -> UInt {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "I")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetIntField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return UInt(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: UInt8.Type) throws -> UInt8 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "B")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetByteField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return UInt8(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: UInt16.Type) throws -> UInt16 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "S")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetShortField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return UInt16(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: UInt32.Type) throws -> UInt32 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "I")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetIntField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return UInt32(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode(_ type: UInt64.Type) throws -> UInt64 {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "J")
|
||||
let javaObject = jniStorage.javaObject
|
||||
let value = JNI.api.GetLongField(JNI.env, javaObject, fieldID)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
return UInt64(fromJavaPrimitive: value)
|
||||
}
|
||||
|
||||
func decode<T>(_ valueType: T.Type) throws -> T where T : Decodable {
|
||||
let classname = decoder.getJavaClassname(forType: valueType)
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: "rawValue", sig: "L\(classname);")
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
guard let object = JNI.api.GetObjectField(JNI.env, javaObject, fieldID) else {
|
||||
throw JavaCodingError.notSupported(javaClass)
|
||||
}
|
||||
|
@ -756,7 +821,11 @@ fileprivate class JavaAnyCodableContainer<K : CodingKey> : KeyedDecodingContaine
|
|||
}
|
||||
}
|
||||
else if key.stringValue == "value" {
|
||||
return try self.decoder.unbox(type: type, javaObject: self.jniStorage.javaObject, codingPath: codingPath + [key])
|
||||
let javaObject = jniStorage.javaObject
|
||||
defer {
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
return try self.decoder.unbox(type: type, javaObject: javaObject!, codingPath: codingPath + [key])
|
||||
}
|
||||
else {
|
||||
fatalError("Unknown key: \(key.stringValue)")
|
||||
|
|
|
@ -66,17 +66,28 @@ indirect enum JNIStorageType {
|
|||
class JNIStorageObject {
|
||||
let type: JNIStorageType
|
||||
let codingPath: [CodingKey]
|
||||
|
||||
private var _javaObject: jobject!
|
||||
|
||||
var javaObject: jobject! {
|
||||
didSet {
|
||||
if let value = oldValue {
|
||||
get {
|
||||
return JNI.api.NewLocalRef(JNI.env, _javaObject)
|
||||
}
|
||||
set {
|
||||
if let value = _javaObject {
|
||||
JNI.api.DeleteLocalRef(JNI.env, value)
|
||||
}
|
||||
_javaObject = newValue
|
||||
}
|
||||
}
|
||||
|
||||
var hasJavaObject: Bool {
|
||||
return _javaObject != nil
|
||||
}
|
||||
|
||||
init(type: JNIStorageType, javaObject: jobject, codingPath: [CodingKey] = []) {
|
||||
self.type = type
|
||||
self.javaObject = javaObject
|
||||
self._javaObject = javaObject
|
||||
self.codingPath = codingPath
|
||||
}
|
||||
|
||||
|
@ -86,7 +97,7 @@ class JNIStorageObject {
|
|||
}
|
||||
|
||||
deinit {
|
||||
if let value = javaObject {
|
||||
if let value = _javaObject {
|
||||
JNI.api.DeleteLocalRef(JNI.env, value)
|
||||
}
|
||||
}
|
||||
|
@ -131,7 +142,7 @@ open class JavaEncoder: Encoder {
|
|||
do {
|
||||
let storage = try self.box(value, codingPath: codingPath)
|
||||
assert(self.javaObjects.count == 0, "Missing encoding for \(self.javaObjects.count) objects")
|
||||
return JNI.api.NewLocalRef(JNI.env, storage.javaObject)!
|
||||
return storage.javaObject!
|
||||
}
|
||||
catch {
|
||||
// clean all reference if failed
|
||||
|
@ -212,45 +223,55 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedEncodingContainerPro
|
|||
self.javaClass = javaClass
|
||||
self.jniStorage = jniStorage
|
||||
}
|
||||
|
||||
private var javaObject: jobject {
|
||||
return jniStorage.javaObject
|
||||
}
|
||||
|
||||
// MARK: Encode JNI primitive fields
|
||||
func encodeBoolean(_ value: jboolean, key: String) throws {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "Z")
|
||||
let javaObject = jniStorage.javaObject
|
||||
JNI.api.SetBooleanField(JNI.env, javaObject, fieldID, value)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
|
||||
func encodeByte(_ value: jbyte, key: String) throws {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "B")
|
||||
let javaObject = jniStorage.javaObject
|
||||
JNI.api.SetByteField(JNI.env, javaObject, fieldID, value)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
|
||||
func encodeShort(_ value: jshort, key: String) throws {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "S")
|
||||
let javaObject = jniStorage.javaObject
|
||||
JNI.api.SetShortField(JNI.env, javaObject, fieldID, value)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
|
||||
func encodeInteger(_ value: jint, key: String) throws {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "I")
|
||||
let javaObject = jniStorage.javaObject
|
||||
JNI.api.SetIntField(JNI.env, javaObject, fieldID, value)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
|
||||
func encodeLong(_ value: jlong, key: String) throws {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "J")
|
||||
let javaObject = jniStorage.javaObject
|
||||
JNI.api.SetLongField(JNI.env, javaObject, fieldID, value)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
|
||||
func encodeFloat(_ value: jfloat, key: String) throws {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "F")
|
||||
let javaObject = jniStorage.javaObject
|
||||
JNI.api.SetFloatField(JNI.env, javaObject, fieldID, value)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
|
||||
func encodeDouble(_ value: jdouble, key: String) throws {
|
||||
let fieldID = try JNI.getJavaField(forClass: javaClass, field: key, sig: "D")
|
||||
let javaObject = jniStorage.javaObject
|
||||
JNI.api.SetDoubleField(JNI.env, javaObject, fieldID, value)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
|
||||
// MARK: - KeyedEncodingContainerProtocol Methods
|
||||
|
@ -402,7 +423,11 @@ fileprivate class JavaObjectContainer<K : CodingKey> : KeyedEncodingContainerPro
|
|||
do {
|
||||
let object = try self.encoder.box(value, codingPath: codingPath + [key])
|
||||
let filed = try JNI.getJavaField(forClass: self.javaClass, field: key.stringValue, sig: object.type.sig)
|
||||
JNI.api.SetObjectField(JNI.env, self.javaObject, filed, object.javaObject)
|
||||
let javaObject = jniStorage.javaObject
|
||||
let javaField = object.javaObject
|
||||
JNI.api.SetObjectField(JNI.env, javaObject, filed, javaField)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
JNI.DeleteLocalRef(javaField)
|
||||
}
|
||||
catch {
|
||||
if self.encoder.missingFieldsStrategy == .ignore {
|
||||
|
@ -455,10 +480,6 @@ fileprivate class JavaHashMapKeyedContainer<K : CodingKey> : KeyedEncodingContai
|
|||
self.jniStorage = jniStorage
|
||||
}
|
||||
|
||||
private var javaObject: jobject {
|
||||
return jniStorage.javaObject
|
||||
}
|
||||
|
||||
// MARK: - KeyedEncodingContainerProtocol Methods
|
||||
public func encodeNil(forKey key: Key) throws {
|
||||
throw EncodingError.invalidValue(NSNotFound, EncodingError.Context(codingPath: codingPath, debugDescription: "Nil not supported"))
|
||||
|
@ -474,7 +495,13 @@ fileprivate class JavaHashMapKeyedContainer<K : CodingKey> : KeyedEncodingContai
|
|||
}
|
||||
|
||||
let valueStorage = try self.encoder.box(value, codingPath: codingPath + [key])
|
||||
let result = JNI.CallObjectMethod(javaObject, methodID: HashMapPutMethod, args: [jvalue(l: keyStorage.javaObject), jvalue(l: valueStorage.javaObject)])
|
||||
let javaObject = jniStorage.javaObject
|
||||
let javaKey = keyStorage.javaObject
|
||||
let javaValue = valueStorage.javaObject
|
||||
let result = JNI.CallObjectMethod(javaObject!, methodID: HashMapPutMethod, args: [jvalue(l: javaKey), jvalue(l: javaValue)])
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
JNI.DeleteLocalRef(javaKey)
|
||||
JNI.DeleteLocalRef(javaValue)
|
||||
assert(result == nil, "Rewrite for key \(key.stringValue)")
|
||||
}
|
||||
|
||||
|
@ -518,10 +545,6 @@ fileprivate class JavaHashMapUnkeyedContainer : UnkeyedEncodingContainer {
|
|||
self.jniStorage = jniStorage
|
||||
}
|
||||
|
||||
private var javaObject: jobject {
|
||||
return jniStorage.javaObject
|
||||
}
|
||||
|
||||
// MARK: - UnkeyedEncodingContainer Methods
|
||||
public func encodeNil() throws {
|
||||
throw EncodingError.invalidValue(NSNotFound, EncodingError.Context(codingPath: codingPath, debugDescription: "Nil not supported"))
|
||||
|
@ -531,7 +554,13 @@ fileprivate class JavaHashMapUnkeyedContainer : UnkeyedEncodingContainer {
|
|||
let indexKey = JavaKey(index: count)
|
||||
let javaValue = try self.encoder.box(value, codingPath: codingPath + [indexKey])
|
||||
if let javaKey = self.javaKey {
|
||||
let result = JNI.CallObjectMethod(javaObject, methodID: HashMapPutMethod, args: [jvalue(l: javaKey.javaObject), jvalue(l: javaValue.javaObject)])
|
||||
let javaObject = jniStorage.javaObject
|
||||
let javaKey = javaKey.javaObject
|
||||
let javaValue = javaValue.javaObject
|
||||
let result = JNI.CallObjectMethod(javaObject!, methodID: HashMapPutMethod, args: [jvalue(l: javaKey), jvalue(l: javaValue)])
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
JNI.DeleteLocalRef(javaKey)
|
||||
JNI.DeleteLocalRef(javaValue)
|
||||
assert(result == nil, "Rewrite for key")
|
||||
self.javaKey = nil
|
||||
}
|
||||
|
@ -575,10 +604,6 @@ fileprivate class JavaArrayContainer : UnkeyedEncodingContainer {
|
|||
self.jniStorage = jniStorage
|
||||
}
|
||||
|
||||
private var javaObject: jobject {
|
||||
return jniStorage.javaObject
|
||||
}
|
||||
|
||||
// MARK: - UnkeyedEncodingContainer Methods
|
||||
public func encodeNil() throws {
|
||||
throw EncodingError.invalidValue(NSNotFound, EncodingError.Context(codingPath: codingPath, debugDescription: "Nil not supported"))
|
||||
|
@ -587,7 +612,11 @@ fileprivate class JavaArrayContainer : UnkeyedEncodingContainer {
|
|||
public func encode<T : Encodable>(_ value: T) throws {
|
||||
let indexKey = JavaKey(index: count)
|
||||
let storeObject = try self.encoder.box(value, codingPath: codingPath + [indexKey])
|
||||
let rewrite = JNI.CallBooleanMethod(self.javaObject, methodID: CollectionAddMethod, args: [jvalue(l: storeObject.javaObject)])
|
||||
let javaObject = jniStorage.javaObject
|
||||
let javaNewValue = storeObject.javaObject
|
||||
let rewrite = JNI.CallBooleanMethod(javaObject!, methodID: CollectionAddMethod, args: [jvalue(l: javaNewValue!)])
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
JNI.DeleteLocalRef(javaNewValue)
|
||||
assert(rewrite == JNI.TRUE, "ArrayList should always return true from add()")
|
||||
count += 1
|
||||
}
|
||||
|
@ -667,7 +696,13 @@ class JavaEnumValueEncodingContainer: SingleValueEncodingContainer {
|
|||
public func encode(_ value: jvalue, sig: String) throws {
|
||||
let clazz = try JNI.getJavaClass(javaClass)
|
||||
// If jniStorage.javaObject == nil its enum, else optionSet
|
||||
if jniStorage.javaObject == nil {
|
||||
if let javaObject = jniStorage.javaObject {
|
||||
let filed = try JNI.getJavaField(forClass: self.javaClass, field: "rawValue", sig: sig)
|
||||
let setterFunc = setterFuncMap[sig]
|
||||
setterFunc?(javaObject, filed, value)
|
||||
JNI.DeleteLocalRef(javaObject)
|
||||
}
|
||||
else {
|
||||
let valueOfMethodID = try JNI.getStaticJavaMethod(forClass: javaClass, method: "valueOf", sig: "(\(sig))L\(javaClass);")
|
||||
guard let javaObject = JNI.CallStaticObjectMethod(clazz, methodID: valueOfMethodID, args: [value]) else {
|
||||
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath,
|
||||
|
@ -675,11 +710,6 @@ class JavaEnumValueEncodingContainer: SingleValueEncodingContainer {
|
|||
}
|
||||
jniStorage.javaObject = javaObject
|
||||
}
|
||||
else {
|
||||
let filed = try JNI.getJavaField(forClass: self.javaClass, field: "rawValue", sig: sig)
|
||||
let setterFunc = setterFuncMap[sig]
|
||||
setterFunc?(self.jniStorage.javaObject, filed, value)
|
||||
}
|
||||
}
|
||||
|
||||
private let setterFuncMap: [String: (jobject, jfieldID, jvalue) -> Void] = [
|
||||
|
@ -693,13 +723,13 @@ class JavaEnumValueEncodingContainer: SingleValueEncodingContainer {
|
|||
let rawValue = try encoder.box(valueType, codingPath: codingPath)
|
||||
let clazz = try JNI.getJavaClass(javaClass)
|
||||
// If jniStorage.javaObject == nil its enum, else optionSet
|
||||
if jniStorage.javaObject == nil {
|
||||
if jniStorage.hasJavaObject == false {
|
||||
let valueOfMethodID = try JNI.getStaticJavaMethod(forClass: javaClass, method: "valueOf", sig: "(\(rawValue.type.sig))L\(javaClass);")
|
||||
JNI.SaveFatalErrorMessage("\(javaClass) valueOf \(rawValue.type.sig)")
|
||||
let javaRawValue = rawValue.javaObject
|
||||
defer {
|
||||
JNI.RemoveFatalErrorMessage()
|
||||
JNI.DeleteLocalRef(javaRawValue)
|
||||
}
|
||||
guard let javaObject = JNI.CallStaticObjectMethod(clazz, methodID: valueOfMethodID, args: [jvalue(l: rawValue.javaObject)]) else {
|
||||
guard let javaObject = JNI.CallStaticObjectMethod(clazz, methodID: valueOfMethodID, args: [jvalue(l: javaRawValue)]) else {
|
||||
throw JavaCodingError.cantCreateObject(javaClass)
|
||||
}
|
||||
jniStorage.javaObject = javaObject
|
||||
|
@ -732,10 +762,6 @@ fileprivate class JavaAnyCodableContainer<K : CodingKey> : KeyedEncodingContaine
|
|||
self.jniStorage = jniStorage
|
||||
}
|
||||
|
||||
private var javaObject: jobject {
|
||||
return jniStorage.javaObject
|
||||
}
|
||||
|
||||
// MARK: - KeyedEncodingContainerProtocol Methods
|
||||
public func encodeNil(forKey key: Key) throws {
|
||||
throw EncodingError.invalidValue(NSNotFound, EncodingError.Context(codingPath: codingPath, debugDescription: "Nil not supported"))
|
||||
|
@ -748,7 +774,7 @@ fileprivate class JavaAnyCodableContainer<K : CodingKey> : KeyedEncodingContaine
|
|||
}
|
||||
do {
|
||||
let jniObject = try self.encoder.box(value, codingPath: codingPath + [key])
|
||||
self.jniStorage.javaObject = JNI.api.NewLocalRef(JNI.env, jniObject.javaObject)
|
||||
self.jniStorage.javaObject = jniObject.javaObject
|
||||
}
|
||||
catch {
|
||||
if self.encoder.missingFieldsStrategy == .ignore {
|
||||
|
|
Loading…
Reference in New Issue