diff --git a/Sources/JavApi/lang/String+Java.swift b/Sources/JavApi/lang/String+Java.swift index dc2795a7..7676848a 100644 --- a/Sources/JavApi/lang/String+Java.swift +++ b/Sources/JavApi/lang/String+Java.swift @@ -188,6 +188,10 @@ extension String { return self } + /// Hashcode of ``String`` + public func hashCode () -> Int { + return self.hashValue + } } fileprivate let TRIM_CHARACTER_SET = CharacterSet(charactersIn : "\u{0000}\u{0001}\u{0002}\u{0003}\u{0004}\u{0005}\u{0006}\u{0007}\u{0008}\u{0009}\u{000A}\u{000B}\u{000C}\u{000D}\u{000E}\u{000F}\u{0010}\u{0011}\u{0012}\u{0013}\u{0014}\u{0015}\u{0016}\u{0017}\u{0018}\u{0019}\u{001A}\u{001B}\u{001C}\u{001D}\u{001E}\u{001F}\u{0020}") // different to strip can be readed f.e. here: (https://stackoverflow.com/questions/51266582/difference-between-string-trim-and-strip-methods-in-java-11) diff --git a/Sources/JavApi/lang/String+Swiftify.swift b/Sources/JavApi/lang/String+Swiftify.swift index bdace4a1..ce159f53 100644 --- a/Sources/JavApi/lang/String+Swiftify.swift +++ b/Sources/JavApi/lang/String+Swiftify.swift @@ -5,6 +5,15 @@ extension String { + // overwrite Foundation.String hashValue with Java like hashCode + var hashValue : Int { + var hash = 0 + for character in self.reversed() { + hash = 31 * hash + Int(character.asciiValue!) + } + return hash + } + /// Returns the bytes of String in given encoding /// - Returns byte array public func getBytes () -> [UInt8] { diff --git a/Sources/JavApi/lang/StringBuilder+Equalable.swift b/Sources/JavApi/lang/StringBuilder+Equalable.swift new file mode 100644 index 00000000..5485b095 --- /dev/null +++ b/Sources/JavApi/lang/StringBuilder+Equalable.swift @@ -0,0 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2024 - Sebastian Ritter + * SPDX-License-Identifier: MIT + */ + +extension StringBuilder : Equatable { + + public static func == (lhs: StringBuilder, rhs: StringBuilder) -> Bool { + return lhs === rhs + } +} diff --git a/Sources/JavApi/lang/StringBuilder+Hashable.swift b/Sources/JavApi/lang/StringBuilder+Hashable.swift new file mode 100644 index 00000000..ad37adc6 --- /dev/null +++ b/Sources/JavApi/lang/StringBuilder+Hashable.swift @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2024 - Sebastian Ritter + * SPDX-License-Identifier: MIT + */ + +import Foundation + +extension StringBuilder : Hashable { + + public var hashValue: Int { + var hasher = Hasher() + hash(into: &hasher) + return hasher.finalize() + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(System.identityHashCode(self)) + hasher.combine(self.content) + } + + // the Java method + public func hashCode () -> Int { + return hashValue + } +} diff --git a/Sources/JavApi/lang/System.swift b/Sources/JavApi/lang/System.swift index fd81fdba..cbfd2351 100644 --- a/Sources/JavApi/lang/System.swift +++ b/Sources/JavApi/lang/System.swift @@ -70,12 +70,12 @@ public struct System { } } - /// Return the value from environment variable - /// - Returns value of environment variable or nil - static public func getenv (_ name : String) -> String? { - return ProcessInfo.processInfo.environment[name] + /// Return the current time in milliseconds + /// + /// - Returns: milliseconds as Int64 + public static func currentTimeMillis () -> Int64 { + return Int64(Date().timeIntervalSince1970.advanced(by: 0)*1_000) } - /// Exits the application /// - Parameters: /// - Parameter status return value e.g. for scripting with your application @@ -85,10 +85,21 @@ public struct System { Foundation.exit(Int32(status)) } - /// Return the current time in milliseconds - /// - /// - Returns: milliseconds as Int64 - public static func currentTimeMillis () -> Int64 { - return Int64(Date().timeIntervalSince1970.advanced(by: 0)*1_000) + /// Returns a hashCode + /// - Note: unsafe + public static func identityHashCode (_ x : AnyObject?) -> Int { + if let x { + return ObjectIdentifier(x).hashValue + } + else { + return 0 + } } + + /// Return the value from environment variable + /// - Returns value of environment variable or nil + public static func getenv (_ name : String) -> String? { + return ProcessInfo.processInfo.environment[name] + } + } diff --git a/Tests/JavApiTests/JavApi_lang_StringBuilder_Tests.swift b/Tests/JavApiTests/JavApi_lang_StringBuilder_Tests.swift new file mode 100644 index 00000000..24f391e5 --- /dev/null +++ b/Tests/JavApiTests/JavApi_lang_StringBuilder_Tests.swift @@ -0,0 +1,32 @@ +/* + * SPDX-FileCopyrightText: 2024 - Sebastian Ritter + * SPDX-License-Identifier: MIT + */ +import XCTest +@testable import JavApi + +final class JavApi_lang_StringBuilder_Tests: XCTestCase { + + func testEquals () { + let a = StringBuilder("1") + let b = StringBuilder("2") + let c = StringBuilder("1") + XCTAssertFalse(a===b); + XCTAssertFalse(a == b) // false + XCTAssertTrue(a == a) // true + XCTAssertFalse(a===c) // false + XCTAssertFalse(a==c) // false + } + + func testHashCode () { + let a = StringBuilder("1") + let b = StringBuilder("2") + let c = StringBuilder("1") + // call twice with same result + XCTAssertEqual(a.hashCode(), a.hashCode()) + // two objects with different content creates different hashCode + XCTAssertNotEqual(a.hashCode(), b.hashCode()) + // two objects with same content creates different hashCode + XCTAssertNotEqual(a.hashCode(), c.hashCode()) + } +}