297 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			297 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| /*
 | |
|  * Copyright (C)2005-2019 Haxe Foundation
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a
 | |
|  * copy of this software and associated documentation files (the "Software"),
 | |
|  * to deal in the Software without restriction, including without limitation
 | |
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | |
|  * and/or sell copies of the Software, and to permit persons to whom the
 | |
|  * Software is furnished to do so, subject to the following conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice shall be included in
 | |
|  * all copies or substantial portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | |
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | |
|  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 | |
|  * DEALINGS IN THE SOFTWARE.
 | |
|  */
 | |
| 
 | |
| package cs;
 | |
| 
 | |
| import cs.system.Type;
 | |
| 
 | |
| /**
 | |
| 	Platform-specific C# Library. Provides some platform-specific functions for the C# target,
 | |
| 	such as conversion from haxe types to native types and vice-versa.
 | |
| **/
 | |
| class Lib {
 | |
| 	private static var decimalSeparator:String;
 | |
| 
 | |
| 	/**
 | |
| 		Changes the current culture settings to allow a consistent cross-target behavior.
 | |
| 		Currently the only change made is in regard to the decimal separator, which is always set to "."
 | |
| 	**/
 | |
| 	public static function applyCultureChanges():Void {
 | |
| 		var ci = new cs.system.globalization.CultureInfo(cs.system.threading.Thread.CurrentThread.CurrentCulture.Name, true);
 | |
| 		decimalSeparator = ci.NumberFormat.NumberDecimalSeparator;
 | |
| 		ci.NumberFormat.NumberDecimalSeparator = ".";
 | |
| 		cs.system.threading.Thread.CurrentThread.CurrentCulture = ci;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Reverts the culture changes to the default settings.
 | |
| 	**/
 | |
| 	public static function revertDefaultCulture():Void {
 | |
| 		var ci = new cs.system.globalization.CultureInfo(cs.system.threading.Thread.CurrentThread.CurrentCulture.Name, true);
 | |
| 		cs.system.threading.Thread.CurrentThread.CurrentCulture = ci;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Returns a native array from the supplied Array. This native array is unsafe to be written on,
 | |
| 		as it may or may not be linked to the actual Array implementation.
 | |
| 
 | |
| 		If equalLengthRequired is true, the result might be a copy of an array with the correct size.
 | |
| 	**/
 | |
| 	extern inline public static function nativeArray<T>(arr:Array<T>, equalLengthRequired:Bool):NativeArray<T> {
 | |
| 		var ret = new cs.NativeArray(arr.length);
 | |
| 		#if erase_generics
 | |
| 		for (i in 0...arr.length)
 | |
| 			ret[i] = arr[i];
 | |
| 		#else
 | |
| 		p_nativeArray(arr, ret);
 | |
| 		#end
 | |
| 		return ret;
 | |
| 	}
 | |
| 
 | |
| 	#if !erase_generics
 | |
| 	static function p_nativeArray<T>(arr:Array<T>, ret:cs.system.Array):Void {
 | |
| 		var native:NativeArray<T> = untyped arr.__a;
 | |
| 		var len = arr.length;
 | |
| 		cs.system.Array.Copy(native, 0, ret, 0, len);
 | |
| 	}
 | |
| 	#end
 | |
| 
 | |
| 	/**
 | |
| 		Provides support for the "as" keyword in C#.
 | |
| 		If the object is not of the supplied type "T", it will return null instead of rasing an exception.
 | |
| 
 | |
| 		This function will not work with Value Types (such as Int, Float, Bool...)
 | |
| 	**/
 | |
| 	@:pure
 | |
| 	extern public static inline function as<T>(obj:Dynamic, cl:Class<T>):T {
 | |
| 		return untyped __as__(obj);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Returns a Class<> equivalent to the native System.Type type.
 | |
| 
 | |
| 		Currently Haxe's Class<> is equivalent to System.Type, but this is an implementation detail.
 | |
| 		This may change in the future, so use this function whenever you need to perform such conversion.
 | |
| 	**/
 | |
| 	public static inline function fromNativeType(t:cs.system.Type):Class<Dynamic> {
 | |
| 		return untyped t;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Returns a System.Type equivalent to the Haxe Class<> type.
 | |
| 
 | |
| 		Currently Haxe's Class<> is equivalent to System.Type, but this is an implementation detail.
 | |
| 		This may change in the future, so use this function whenever you need to perform such conversion.
 | |
| 	**/
 | |
| 	public static inline function toNativeType(cl:Class<Dynamic>):Type {
 | |
| 		return untyped cl;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Returns a System.Type equivalent to the Haxe Enum<> type.
 | |
| 	**/
 | |
| 	public static inline function toNativeEnum(cl:Enum<Dynamic>):Type {
 | |
| 		return untyped cl;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Gets the native System.Type from the supplied object. Will throw an exception in case of null being passed.
 | |
| 		[deprecated] - use `getNativeType` instead
 | |
| 	**/
 | |
| 	@:deprecated('The function `nativeType` is deprecated and will be removed in later versions. Please use `getNativeType` instead')
 | |
| 	public static inline function nativeType(obj:Dynamic):Type {
 | |
| 		return untyped obj.GetType();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Gets the native System.Type from the supplied object. Will throw an exception in case of null being passed.
 | |
| 	**/
 | |
| 	public static inline function getNativeType(obj:Dynamic):Type {
 | |
| 		return untyped obj.GetType();
 | |
| 	}
 | |
| 
 | |
| 	#if erase_generics
 | |
| 	inline private static function mkDynamic<T>(native:NativeArray<T>):NativeArray<Dynamic> {
 | |
| 		var ret = new cs.NativeArray<Dynamic>(native.Length);
 | |
| 		for (i in 0...native.Length)
 | |
| 			ret[i] = native[i];
 | |
| 		return ret;
 | |
| 	}
 | |
| 	#end
 | |
| 
 | |
| 	/**
 | |
| 		Returns a Haxe Array of a native Array.
 | |
| 		Unless `erase_generics` is defined, it won't copy the contents of the native array,
 | |
| 		so unless any operation triggers an array resize, all changes made to the Haxe array
 | |
| 		will affect the native array argument.
 | |
| 	**/
 | |
| 	inline public static function array<T>(native:cs.NativeArray<T>):Array<T> {
 | |
| 		#if erase_generics
 | |
| 		var dyn:NativeArray<Dynamic> = mkDynamic(native);
 | |
| 		return @:privateAccess Array.ofNative(dyn);
 | |
| 		#else
 | |
| 		return @:privateAccess Array.ofNative(native);
 | |
| 		#end
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Allocates a new Haxe Array with a predetermined size
 | |
| 	**/
 | |
| 	inline public static function arrayAlloc<T>(size:Int):Array<T> {
 | |
| 		return @:privateAccess Array.alloc(size);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Rethrow an exception. This is useful when manually filtering an exception in order
 | |
| 		to keep the previous exception stack.
 | |
| 	**/
 | |
| 	extern inline public static function rethrow(e:Dynamic):Void {
 | |
| 		throw untyped __rethrow__;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Creates a "checked" block, which throws exceptions for overflows.
 | |
| 
 | |
| 		Usage:
 | |
| 			cs.Lib.checked({
 | |
| 				var x = 1000;
 | |
| 				while(true)
 | |
| 				{
 | |
| 					x *= x;
 | |
| 				}
 | |
| 			});
 | |
| 		This method only exists at compile-time, so it can't be called via reflection.
 | |
| 	**/
 | |
| 	extern public static inline function checked<V>(block:V):Void {
 | |
| 		untyped __checked__(block);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Ensures that one thread does not enter a critical section of code while another thread
 | |
| 		is in the critical section. If another thread attempts to enter a locked code, it
 | |
| 		will wait, block, until the object is released.
 | |
| 
 | |
| 		This method only exists at compile-time, so it can't be called via reflection.
 | |
| 	**/
 | |
| 	extern public static inline function lock<O, V>(obj:O, block:V):Void {
 | |
| 		untyped __lock__(obj, block);
 | |
| 	}
 | |
| 
 | |
| 	// Unsafe code manipulation
 | |
| 
 | |
| 	#if unsafe
 | |
| 	/**
 | |
| 		Marks its parameters as fixed objects inside the defined block.
 | |
| 		The first variable declarations that use cs.Lib.pointerOfArray() will be the fixed definitions.
 | |
| 		Usage:
 | |
| 			cs.Lib.fixed({
 | |
| 				var obj1 = cs.Lib.pointerOfArray(someArray);
 | |
| 				var obj2 = cs.Lib.pointerOfArray(someArray2);
 | |
| 				var obj3 = cs.Lib.pointerOfArray(someArray3);
 | |
| 				//from now on, obj1, obj2 and obj3 are fixed
 | |
| 				//we cannot change obj1, obj2 or obj3 variables like this:
 | |
| 				//obj1++;
 | |
| 			});
 | |
| 
 | |
| 		This method only exists at compile-time, so it can't be called via reflection.
 | |
| 	**/
 | |
| 	extern public static inline function fixed<V>(block:V):Void {
 | |
| 		untyped __fixed__(block);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Marks the contained block as an unsafe block, meaning that it can contain unsafe code.
 | |
| 		Usage:
 | |
| 			cs.Lib.unsafe({
 | |
| 				//unsafe code is allowed inside here
 | |
| 			});
 | |
| 
 | |
| 		This method only exists at compile-time, so it can't be called via reflection.
 | |
| 	**/
 | |
| 	extern public static inline function unsafe<V>(block:V):Void {
 | |
| 		untyped __unsafe__(block);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Gets the pointer to the address of current local. Equivalent to the "&" operator in C#
 | |
| 		Usage:
 | |
| 			var x:Int = 0;
 | |
| 			cs.Lib.unsafe({
 | |
| 				var addr = cs.Lib.addressOf(x);
 | |
| 				x[0] = 42;
 | |
| 			});
 | |
| 			trace(x); //42
 | |
| 
 | |
| 		This method only exists at compile-time, so it can't be called via reflection.
 | |
| 		Warning: This method will only work if a local variable is passed as an argument.
 | |
| 	**/
 | |
| 	extern public static inline function addressOf<T>(variable:T):cs.Pointer<T> {
 | |
| 		return untyped __addressOf__(variable);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Gets the value of the pointer address.
 | |
| 		Usage:
 | |
| 			var x:Int = 0;
 | |
| 			cs.Lib.unsafe({
 | |
| 				var addr = cs.Lib.addressOf(x);
 | |
| 				trace(cs.Lib.valueOf(addr)); //0
 | |
| 				addr[0] = 42;
 | |
| 				trace(cs.Lib.valueOf(addr)); //42
 | |
| 			});
 | |
| 			trace(x); //42
 | |
| 
 | |
| 		This method only exists at compile-time, so it can't be called via reflection.
 | |
| 	**/
 | |
| 	extern public static inline function valueOf<T>(pointer:cs.Pointer<T>):T {
 | |
| 		return untyped __valueOf__(pointer);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Transforms a managed native array into a Pointer. Must be inside a fixed statement
 | |
| 		Usage:
 | |
| 			var x:cs.NativeArray<Int> = new cs.NativeArray(1);
 | |
| 			cs.Lib.unsafe({
 | |
| 				cs.Lib.fixed({
 | |
| 					var addr = cs.Lib.pointerOfArray(x);
 | |
| 					trace(cs.Lib.valueOf(addr)); //0
 | |
| 					addr[0] = 42;
 | |
| 					trace(cs.Lib.valueOf(addr)); //42
 | |
| 				});
 | |
| 			});
 | |
| 			trace(x[0]); //42
 | |
| 
 | |
| 		This method only exists at compile-time, so it can't be called via reflection.
 | |
| 	**/
 | |
| 	extern public static inline function pointerOfArray<T>(array:cs.NativeArray<T>):cs.Pointer<T> {
 | |
| 		return untyped __ptr__(array);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Returns the byte size of the given struct. Only works with structs and basic types.
 | |
| 	**/
 | |
| 	extern public static inline function sizeof(struct:Class<Dynamic>):Int {
 | |
| 		return untyped __sizeof__(struct);
 | |
| 	}
 | |
| 	#end
 | |
| }
 |