Update Files

This commit is contained in:
2025-01-22 16:18:30 +01:00
parent ed4603cf95
commit a36294b518
16718 changed files with 2960346 additions and 0 deletions

View File

@ -0,0 +1,185 @@
/*
* 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 haxe;
/**
Elements return by `CallStack` methods.
**/
enum StackItem {
CFunction;
Module(m:String);
FilePos(s:Null<StackItem>, file:String, line:Int, ?column:Int);
Method(classname:Null<String>, method:String);
LocalFunction(?v:Int);
}
/**
Get information about the call stack.
**/
@:allow(haxe.Exception)
@:using(haxe.CallStack)
abstract CallStack(Array<StackItem>) from Array<StackItem> {
/**
The length of this stack.
**/
public var length(get,never):Int;
inline function get_length():Int return this.length;
/**
Return the call stack elements, or an empty array if not available.
**/
public static function callStack():Array<StackItem> {
return NativeStackTrace.toHaxe(NativeStackTrace.callStack());
}
/**
Return the exception stack : this is the stack elements between
the place the last exception was thrown and the place it was
caught, or an empty array if not available.
Set `fullStack` parameter to true in order to return the full exception stack.
May not work if catch type was a derivative from `haxe.Exception`.
**/
public static function exceptionStack( fullStack = false ):Array<StackItem> {
var eStack:CallStack = NativeStackTrace.toHaxe(NativeStackTrace.exceptionStack());
return (fullStack ? eStack : eStack.subtract(callStack())).asArray();
}
/**
Returns a representation of the stack as a printable string.
**/
static public function toString(stack:CallStack):String {
var b = new StringBuf();
for (s in stack.asArray()) {
b.add('\nCalled from ');
itemToString(b, s);
}
return b.toString();
}
/**
Returns a range of entries of current stack from the beginning to the the
common part of this and `stack`.
**/
public function subtract(stack:CallStack):CallStack {
var startIndex = -1;
var i = -1;
while(++i < this.length) {
for(j in 0...stack.length) {
if(equalItems(this[i], stack[j])) {
if(startIndex < 0) {
startIndex = i;
}
++i;
if(i >= this.length) break;
} else {
startIndex = -1;
}
}
if(startIndex >= 0) break;
}
return startIndex >= 0 ? this.slice(0, startIndex) : this;
}
/**
Make a copy of the stack.
**/
public inline function copy():CallStack {
return this.copy();
}
@:arrayAccess public inline function get(index:Int):StackItem {
return this[index];
}
inline function asArray():Array<StackItem> {
return this;
}
static function equalItems(item1:Null<StackItem>, item2:Null<StackItem>):Bool {
return switch([item1, item2]) {
case [null, null]: true;
case [CFunction, CFunction]: true;
case [Module(m1), Module(m2)]:
m1 == m2;
case [FilePos(item1, file1, line1, col1), FilePos(item2, file2, line2, col2)]:
file1 == file2 && line1 == line2 && col1 == col2 && equalItems(item1, item2);
case [Method(class1, method1), Method(class2, method2)]:
class1 == class2 && method1 == method2;
case [LocalFunction(v1), LocalFunction(v2)]:
v1 == v2;
case _: false;
}
}
static function exceptionToString(e:Exception):String {
if(e.previous == null) {
return 'Exception: ${e.toString()}${e.stack}';
}
var result = '';
var e:Null<Exception> = e;
var prev:Null<Exception> = null;
while(e != null) {
if(prev == null) {
result = 'Exception: ${e.message}${e.stack}' + result;
} else {
var prevStack = @:privateAccess e.stack.subtract(prev.stack);
result = 'Exception: ${e.message}${prevStack}\n\nNext ' + result;
}
prev = e;
e = e.previous;
}
return result;
}
static function itemToString(b:StringBuf, s) {
switch (s) {
case CFunction:
b.add("a C function");
case Module(m):
b.add("module ");
b.add(m);
case FilePos(s, file, line, col):
if (s != null) {
itemToString(b, s);
b.add(" (");
}
b.add(file);
b.add(" line ");
b.add(line);
if (col != null) {
b.add(" column ");
b.add(col);
}
if (s != null)
b.add(")");
case Method(cname, meth):
b.add(cname == null ? "<unknown>" : cname);
b.add(".");
b.add(meth);
case LocalFunction(n):
b.add("local function #");
b.add(n);
}
}
}

View File

@ -0,0 +1,78 @@
/*
* 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 haxe;
/**
This type unifies with any function type.
It is intended to be used as a type parameter constraint. If used as a real
type, the underlying type will be `Dynamic`.
**/
@:callable
abstract Function(Dynamic) {}
/**
This type unifies with an enum instance if all constructors of the enum
require no arguments.
It is intended to be used as a type parameter constraint. If used as a real
type, the underlying type will be `Dynamic`.
**/
abstract FlatEnum(Dynamic) {}
/**
This type unifies with anything but `Void`.
It is intended to be used as a type parameter constraint. If used as a real
type, the underlying type will be `Dynamic`.
**/
abstract NotVoid(Dynamic) { }
/**
This type unifies with any instance of classes that have a constructor
which
* is `public` and
* unifies with the type used for type parameter `T`.
If a type parameter `A` is assigned to a type parameter `B` which is constrained
to `Constructible<T>`, A must be explicitly constrained to
`Constructible<T>` as well.
It is intended to be used as a type parameter constraint. If used as a real
type, the underlying type will be `Dynamic`.
**/
abstract Constructible<T>(Dynamic) {}
interface IMap<K, V> {
function get(k:K):Null<V>;
function set(k:K, v:V):Void;
function exists(k:K):Bool;
function remove(k:K):Bool;
function keys():Iterator<K>;
function iterator():Iterator<V>;
function keyValueIterator():KeyValueIterator<K, V>;
function copy():IMap<K, V>;
function toString():String;
function clear():Void;
}

View File

@ -0,0 +1,125 @@
/*
* 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 haxe;
import haxe.iterators.DynamicAccessIterator;
import haxe.iterators.DynamicAccessKeyValueIterator;
/**
DynamicAccess is an abstract type for working with anonymous structures
that are intended to hold collections of objects by the string key.
For example, these types of structures are often created from JSON.
Basically, it wraps `Reflect` calls in a `Map`-like interface.
**/
abstract DynamicAccess<T>(Dynamic<T>) from Dynamic<T> to Dynamic<T> {
/**
Creates a new structure.
**/
public inline function new()
this = {};
/**
Returns a value by specified `key`.
If the structure does not contain the given key, `null` is returned.
If `key` is `null`, the result is unspecified.
**/
@:arrayAccess
public inline function get(key:String):Null<T> {
#if js
return untyped this[key]; // we know it's an object, so we don't need a check
#else
return Reflect.field(this, key);
#end
}
/**
Sets a `value` for a specified `key`.
If the structure contains the given key, its value will be overwritten.
Returns the given value.
If `key` is `null`, the result is unspecified.
**/
@:arrayAccess
public inline function set(key:String, value:T):T {
#if js
return untyped this[key] = value;
#else
Reflect.setField(this, key, value);
return value;
#end
}
/**
Tells if the structure contains a specified `key`.
If `key` is `null`, the result is unspecified.
**/
public inline function exists(key:String):Bool
return Reflect.hasField(this, key);
/**
Removes a specified `key` from the structure.
Returns true, if `key` was present in structure, or false otherwise.
If `key` is `null`, the result is unspecified.
**/
public inline function remove(key:String):Bool
return Reflect.deleteField(this, key);
/**
Returns an array of `keys` in a structure.
**/
public inline function keys():Array<String>
return Reflect.fields(this);
/**
Returns a shallow copy of the structure
**/
public inline function copy():DynamicAccess<T>
return Reflect.copy(this);
/**
Returns an Iterator over the values of this `DynamicAccess`.
The order of values is undefined.
**/
public inline function iterator():DynamicAccessIterator<T> {
return new DynamicAccessIterator(this);
}
/**
Returns an Iterator over the keys and values of this `DynamicAccess`.
The order of values is undefined.
**/
public inline function keyValueIterator():DynamicAccessKeyValueIterator<T> {
return new DynamicAccessKeyValueIterator(this);
}
}

View File

@ -0,0 +1,165 @@
package haxe;
#if (target.threaded && !cppia)
import sys.thread.Lock;
import sys.thread.Mutex;
import sys.thread.Thread;
#elseif sys
private class Lock {
public function new() {}
public inline function release() {}
public inline function wait(?t:Float) {}
}
private class Mutex {
public function new() {}
public inline function acquire() {}
public inline function release() {}
}
private class Thread {
public static function create(f:Void->Void) {
f();
}
}
#end
/**
If `haxe.MainLoop` is kept from DCE, then we will insert an `haxe.EntryPoint.run()` call just at then end of `main()`.
This class can be redefined by custom frameworks so they can handle their own main loop logic.
**/
class EntryPoint {
#if sys
static var mutex = new Mutex();
#if (target.threaded && !cppia)
static var mainThread:Thread = Thread.current();
#else
static var sleepLock = new Lock();
#end
#end
static var pending = new Array<Void->Void>();
public static var threadCount(default, null):Int = 0;
/**
Wakeup a sleeping `run()`
**/
public static function wakeup() {
#if (sys && !(target.threaded && !cppia))
sleepLock.release();
#end
}
public static function runInMainThread(f:Void->Void) {
#if sys
#if (target.threaded && !cppia)
mainThread.events.run(f);
#else
mutex.acquire();
pending.push(f);
mutex.release();
wakeup();
#end
#else
pending.push(f);
#end
}
public static function addThread(f:Void->Void) {
#if sys
mutex.acquire();
threadCount++;
mutex.release();
#if (target.threaded && !cppia)
mainThread.events.promise();
#end
Thread.create(function() {
f();
mutex.acquire();
threadCount--;
if (threadCount == 0)
wakeup();
mutex.release();
#if (target.threaded && !cppia)
mainThread.events.runPromised(() -> {});
#end
});
#else
threadCount++;
pending.push(function() {
f();
threadCount--;
});
#end
}
static function processEvents():Float {
#if (target.threaded && !cppia)
return -1;
#else
// flush all pending calls
while (true) {
#if sys
mutex.acquire();
var f = pending.shift();
mutex.release();
#else
var f = pending.shift();
#end
if (f == null)
break;
f();
}
var time = @:privateAccess MainLoop.tick();
if (!MainLoop.hasEvents() && threadCount == 0)
return -1;
return time;
#end
}
/**
Start the main loop. Depending on the platform, this can return immediately or will only return when the application exits.
**/
@:keep public static function run() @:privateAccess {
#if js
var nextTick = processEvents();
inline function setTimeoutNextTick() {
if (nextTick >= 0) {
(untyped setTimeout)(run, nextTick * 1000);
}
}
#if nodejs
setTimeoutNextTick();
#else
if(js.Lib.typeof(js.Browser.window) != 'undefined') {
var window:Dynamic = js.Browser.window;
var rqf:Dynamic = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame;
if(rqf != null) {
rqf(run);
} else {
setTimeoutNextTick();
}
} else {
setTimeoutNextTick();
}
#end
#elseif flash
flash.Lib.current.stage.addEventListener(flash.events.Event.ENTER_FRAME, function(_) processEvents());
#elseif (target.threaded && !cppia)
//everything is delegated to sys.thread.EventLoop
#elseif sys
while (true) {
var nextTick = processEvents();
if (nextTick < 0)
break;
if (nextTick > 0)
sleepLock.wait(nextTick); // wait until nextTick or wakeup() call
}
#else
// no implementation available, let's exit immediately
#end
}
}

View File

@ -0,0 +1,94 @@
/*
* 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 haxe;
/**
A typed interface for bit flags. This is not a real object, only a typed
interface for an actual Int. Each flag can be tested/set with the
corresponding enum instance. Up to 32 flags can be stored that way.
Enum constructor indices are preserved from Haxe syntax, so the first
declared is index 0, the next index 1 etc. The methods are optimized if the
enum instance is passed directly, e.g. as `has(EnumCtor)`. Otherwise
`Type.enumIndex()` reflection is used.
**/
abstract EnumFlags<T:EnumValue>(Int) {
/**
Initializes the bitflags to `i`.
**/
public inline function new(i = 0) {
this = i;
}
/**
Checks if the index of enum instance `v` is set.
This method is optimized if `v` is an enum instance expression such as
`SomeEnum.SomeCtor`.
If `v` is `null`, the result is unspecified.
**/
public inline function has(v:T):Bool {
return this & (1 << Type.enumIndex(v)) != 0;
}
/**
Sets the index of enum instance `v`.
This method is optimized if `v` is an enum instance expression such as
`SomeEnum.SomeCtor`.
If `v` is `null`, the result is unspecified.
**/
public inline function set(v:T):Void {
this |= 1 << Type.enumIndex(v);
}
/**
Unsets the index of enum instance `v`.
This method is optimized if `v` is an enum instance expression such as
`SomeEnum.SomeCtor`.
If `v` is `null`, the result is unspecified.
**/
public inline function unset(v:T):Void {
this &= 0xFFFFFFFF - (1 << Type.enumIndex(v));
}
/**
Convert a integer bitflag into a typed one (this is a no-op, it does not
have any impact on speed).
**/
public inline static function ofInt<T:EnumValue>(i:Int):EnumFlags<T> {
return new EnumFlags<T>(i);
}
/**
Convert the typed bitflag into the corresponding int value (this is a
no-op, it doesn't have any impact on speed).
**/
public inline function toInt():Int {
return this;
}
}

View File

@ -0,0 +1,173 @@
/*
* 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 haxe;
/**
This class provides advanced methods on enums. It is ideally used with
`using EnumTools` and then acts as an
[extension](https://haxe.org/manual/lf-static-extension.html) to the
`enum` types.
If the first argument to any of the methods is `null`, the result is
unspecified.
**/
extern class EnumTools {
/**
Returns the name of enum `e`, including its path.
If `e` is inside a package, the package structure is returned dot-
separated, with another dot separating the enum name:
pack1.pack2.(...).packN.EnumName
If `e` is a sub-type of a Haxe module, that module is not part of the
package structure.
If `e` has no package, the enum name is returned.
If `e` is `null`, the result is unspecified.
The enum name does not include any type parameters.
**/
static inline function getName<T>(e:Enum<T>):String {
return Type.getEnumName(e);
}
/**
Creates an instance of enum `e` by calling its constructor `constr` with
arguments `params`.
If `e` or `constr` is `null`, or if enum `e` has no constructor named
`constr`, or if the number of elements in `params` does not match the
expected number of constructor arguments, or if any argument has an
invalid type, the result is unspecified.
**/
static inline function createByName<T>(e:Enum<T>, constr:String, ?params:Array<Dynamic>):T {
return Type.createEnum(e, constr, params);
}
/**
Creates an instance of enum `e` by calling its constructor number
`index` with arguments `params`.
The constructor indices are preserved from Haxe syntax, so the first
declared is index 0, the next index 1 etc.
If `e` or `index` is `null`, or if enum `e` has no constructor
corresponding to index `index`, or if the number of elements in `params`
does not match the expected number of constructor arguments, or if any
argument has an invalid type, the result is unspecified.
**/
static inline function createByIndex<T>(e:Enum<T>, index:Int, ?params:Array<Dynamic>):T {
return Type.createEnumIndex(e, index, params);
}
/**
Returns a list of all constructors of enum `e` that require no
arguments.
This may return the empty Array `[]` if all constructors of `e` require
arguments.
Otherwise an instance of `e` constructed through each of its non-
argument constructors is returned, in the order of the constructor
declaration.
If `e` is `null`, the result is unspecified.
**/
static inline function createAll<T>(e:Enum<T>):Array<T> {
return Type.allEnums(e);
}
/**
Returns a list of the names of all constructors of enum `e`.
The order of the constructor names in the returned Array is preserved
from the original syntax.
If `c` is `null`, the result is unspecified.
**/
static inline function getConstructors<T>(e:Enum<T>):Array<String> {
return Type.getEnumConstructs(e);
}
}
/**
This class provides advanced methods on enum values. It is ideally used with
`using EnumValueTools` and then acts as an
[extension](https://haxe.org/manual/lf-static-extension.html) to the
`EnumValue` types.
If the first argument to any of the methods is `null`, the result is
unspecified.
**/
extern class EnumValueTools {
/**
Recursively compares two enum instances `a` and `b` by value.
Unlike `a == b`, this function performs a deep equality check on the
arguments of the constructors (if there are any).
If `a` or `b` are `null`, the result is unspecified.
**/
static inline function equals<T:EnumValue>(a:T, b:T):Bool {
return Type.enumEq(a, b);
}
/**
Returns the constructor name of enum instance `e`.
The result String does not contain any constructor arguments.
If `e` is `null`, the result is unspecified.
**/
static inline function getName(e:EnumValue):String {
return Type.enumConstructor(e);
}
/**
Returns a list of the constructor arguments of enum instance `e`.
If `e` has no arguments, the result is `[]`.
Otherwise the result are the values that were used as arguments to `e`,
in the order of their declaration.
If `e` is `null`, the result is unspecified.
**/
static inline function getParameters(e:EnumValue):Array<Dynamic> {
return Type.enumParameters(e);
}
/**
Returns the index of enum instance `e`.
This corresponds to the original syntactic position of `e`. The index of
the first declared constructor is 0, the next one is 1 etc.
If `e` is `null`, the result is unspecified.
**/
static inline function getIndex(e:EnumValue):Int {
return Type.enumIndex(e);
}
}

View File

@ -0,0 +1,117 @@
package haxe;
/**
Base class for exceptions.
If this class (or derivatives) is used to catch an exception, then
`haxe.CallStack.exceptionStack()` will not return a stack for the exception
caught. Use `haxe.Exception.stack` property instead:
```haxe
try {
throwSomething();
} catch(e:Exception) {
trace(e.stack);
}
```
Custom exceptions should extend this class:
```haxe
class MyException extends haxe.Exception {}
//...
throw new MyException('terrible exception');
```
`haxe.Exception` is also a wildcard type to catch any exception:
```haxe
try {
throw 'Catch me!';
} catch(e:haxe.Exception) {
trace(e.message); // Output: Catch me!
}
```
To rethrow an exception just throw it again.
Haxe will try to rethrow an original native exception whenever possible.
```haxe
try {
var a:Array<Int> = null;
a.push(1); // generates target-specific null-pointer exception
} catch(e:haxe.Exception) {
throw e; // rethrows native exception instead of haxe.Exception
}
```
**/
extern class Exception {
/**
Exception message.
**/
public var message(get,never):String;
private function get_message():String;
/**
The call stack at the moment of the exception creation.
**/
public var stack(get,never):CallStack;
private function get_stack():CallStack;
/**
Contains an exception, which was passed to `previous` constructor argument.
**/
public var previous(get,never):Null<Exception>;
private function get_previous():Null<Exception>;
/**
Native exception, which caused this exception.
**/
public var native(get,never):Any;
final private function get_native():Any;
/**
Used internally for wildcard catches like `catch(e:Exception)`.
**/
static private function caught(value:Any):Exception;
/**
Used internally for wrapping non-throwable values for `throw` expressions.
**/
static private function thrown(value:Any):Any;
/**
Create a new Exception instance.
The `previous` argument could be used for exception chaining.
The `native` argument is for internal usage only.
There is no need to provide `native` argument manually and no need to keep it
upon extending `haxe.Exception` unless you know what you're doing.
**/
public function new(message:String, ?previous:Exception, ?native:Any):Void;
/**
Extract an originally thrown value.
Used internally for catching non-native exceptions.
Do _not_ override unless you know what you are doing.
**/
private function unwrap():Any;
/**
Returns exception message.
**/
public function toString():String;
/**
Detailed exception description.
Includes message, stack and the chain of previous exceptions (if set).
**/
public function details():String;
/**
If this field is defined in a target implementation, then a call to this
field will be generated automatically in every constructor of derived classes
to make exception stacks point to derived constructor invocations instead of
`super` calls.
**/
// @:noCompletion @:ifFeature("haxe.Exception.stack") private function __shiftStack():Void;
}

View File

@ -0,0 +1,33 @@
/*
* 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 haxe;
#if sys
typedef Http = sys.Http;
#elseif nodejs
typedef Http = haxe.http.HttpNodeJs;
#elseif js
typedef Http = haxe.http.HttpJs;
#else
typedef Http = haxe.http.HttpBase;
#end

View File

@ -0,0 +1,282 @@
/*
* 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 haxe;
/**
Int32 provides a 32-bit integer with consistent overflow behavior across
all platforms.
**/
@:transitive
abstract Int32(Int) from Int to Int {
@:op(-A) private inline function negate():Int32
return clamp(~this + 1);
@:op(++A) private inline function preIncrement():Int32
return this = clamp(++this);
@:op(A++) private inline function postIncrement():Int32 {
var ret = this++;
this = clamp(this);
return ret;
}
@:op(--A) private inline function preDecrement():Int32
return this = clamp(--this);
@:op(A--) private inline function postDecrement():Int32 {
var ret = this--;
this = clamp(this);
return ret;
}
@:op(A + B) private static inline function add(a:Int32, b:Int32):Int32
return clamp((a : Int) + (b : Int));
@:op(A + B) @:commutative private static inline function addInt(a:Int32, b:Int):Int32
return clamp((a : Int) + (b : Int));
@:op(A + B) @:commutative private static function addFloat(a:Int32, b:Float):Float;
@:op(A - B) private static inline function sub(a:Int32, b:Int32):Int32
return clamp((a : Int) - (b : Int));
@:op(A - B) private static inline function subInt(a:Int32, b:Int):Int32
return clamp((a : Int) - (b : Int));
@:op(A - B) private static inline function intSub(a:Int, b:Int32):Int32
return clamp((a : Int) - (b : Int));
@:op(A - B) private static function subFloat(a:Int32, b:Float):Float;
@:op(A - B) private static function floatSub(a:Float, b:Int32):Float;
#if (js || php || python || lua)
#if js
// on JS we want to try using Math.imul, but we have to assign that function to Int32.mul only once,
// or else V8 will deoptimize it, so we need to be a bit funky with this.
// See https://github.com/HaxeFoundation/haxe/issues/5367 for benchmarks.
@:op(A * B) inline static function mul(a:Int32, b:Int32):Int32
return _mul(a, b);
static var _mul:Int32->Int32->Int32 = untyped if (Math.imul != null)
Math.imul
else
function(a:Int32, b:Int32):Int32 return clamp((a : Int) * ((b : Int) & 0xFFFF) + clamp((a : Int) * ((b : Int) >>> 16) << 16));
#else
@:op(A * B) private static function mul(a:Int32, b:Int32):Int32
return clamp((a : Int) * ((b : Int) & 0xFFFF) + clamp((a : Int) * ((b : Int) >>> 16) << 16));
#end
@:op(A * B) @:commutative private static inline function mulInt(a:Int32, b:Int):Int32
return mul(a, b);
#else
@:op(A * B) private static function mul(a:Int32, b:Int32):Int32;
@:op(A * B) @:commutative private static function mulInt(a:Int32, b:Int):Int32;
#end
@:op(A * B) @:commutative private static function mulFloat(a:Int32, b:Float):Float;
@:op(A / B) private static function div(a:Int32, b:Int32):Float;
@:op(A / B) private static function divInt(a:Int32, b:Int):Float;
@:op(A / B) private static function intDiv(a:Int, b:Int32):Float;
@:op(A / B) private static function divFloat(a:Int32, b:Float):Float;
@:op(A / B) private static function floatDiv(a:Float, b:Int32):Float;
@:op(A % B) private static function mod(a:Int32, b:Int32):Int32;
@:op(A % B) private static function modInt(a:Int32, b:Int):Int;
@:op(A % B) private static function intMod(a:Int, b:Int32):Int;
@:op(A % B) private static function modFloat(a:Int32, b:Float):Float;
@:op(A % B) private static function floatMod(a:Float, b:Int32):Float;
@:op(A == B) private static function eq(a:Int32, b:Int32):Bool;
@:op(A == B) @:commutative private static function eqInt(a:Int32, b:Int):Bool;
@:op(A == B) @:commutative private static function eqFloat(a:Int32, b:Float):Bool;
@:op(A != B) private static function neq(a:Int32, b:Int32):Bool;
@:op(A != B) @:commutative private static function neqInt(a:Int32, b:Int):Bool;
@:op(A != B) @:commutative private static function neqFloat(a:Int32, b:Float):Bool;
@:op(A < B) private static function lt(a:Int32, b:Int32):Bool;
@:op(A < B) private static function ltInt(a:Int32, b:Int):Bool;
@:op(A < B) private static function intLt(a:Int, b:Int32):Bool;
@:op(A < B) private static function ltFloat(a:Int32, b:Float):Bool;
@:op(A < B) private static function floatLt(a:Float, b:Int32):Bool;
@:op(A <= B) private static function lte(a:Int32, b:Int32):Bool;
@:op(A <= B) private static function lteInt(a:Int32, b:Int):Bool;
@:op(A <= B) private static function intLte(a:Int, b:Int32):Bool;
@:op(A <= B) private static function lteFloat(a:Int32, b:Float):Bool;
@:op(A <= B) private static function floatLte(a:Float, b:Int32):Bool;
@:op(A > B) private static function gt(a:Int32, b:Int32):Bool;
@:op(A > B) private static function gtInt(a:Int32, b:Int):Bool;
@:op(A > B) private static function intGt(a:Int, b:Int32):Bool;
@:op(A > B) private static function gtFloat(a:Int32, b:Float):Bool;
@:op(A > B) private static function floatGt(a:Float, b:Int32):Bool;
@:op(A >= B) private static function gte(a:Int32, b:Int32):Bool;
@:op(A >= B) private static function gteInt(a:Int32, b:Int):Bool;
@:op(A >= B) private static function intGte(a:Int, b:Int32):Bool;
@:op(A >= B) private static function gteFloat(a:Int32, b:Float):Bool;
@:op(A >= B) private static function floatGte(a:Float, b:Int32):Bool;
#if (lua || python || php)
@:op(~A) private static inline function complement(a:Int32):Int32
#if lua return lua.Boot.clampInt32(~a); #else return clamp(~a); #end
#else
@:op(~A) private function complement():Int32;
#end
@:op(A & B) private static function and(a:Int32, b:Int32):Int32;
@:op(A & B) @:commutative private static function andInt(a:Int32, b:Int):Int32;
#if (lua || python || php)
@:op(A | B) private static #if (python || php) inline #end function or(a:Int32, b:Int32):Int32
return clamp((a : Int) | (b : Int));
@:op(A | B) @:commutative private #if (python || php) inline #end static function orInt(a:Int32, b:Int):Int32
return clamp((a : Int) | b);
#else
@:op(A | B) private static function or(a:Int32, b:Int32):Int32;
@:op(A | B) @:commutative private static function orInt(a:Int32, b:Int):Int32;
#end
#if (lua || python || php)
@:op(A ^ B) private static #if (python || php) inline #end function xor(a:Int32, b:Int32):Int32
return clamp((a : Int) ^ (b : Int));
@:op(A ^ B) @:commutative private static #if (python || php) inline #end function xorInt(a:Int32, b:Int):Int32
return clamp((a : Int) ^ b);
#else
@:op(A ^ B) private static function xor(a:Int32, b:Int32):Int32;
@:op(A ^ B) @:commutative private static function xorInt(a:Int32, b:Int):Int32;
#end
#if (lua || python || php)
@:op(A >> B) private static #if (python || php) inline #end function shr(a:Int32, b:Int32):Int32
return clamp((a : Int) >> (b : Int));
@:op(A >> B) private static #if (python || php) inline #end function shrInt(a:Int32, b:Int):Int32
return clamp((a : Int) >> b);
@:op(A >> B) private static #if (python || php) inline #end function intShr(a:Int, b:Int32):Int32
return clamp(a >> (b : Int));
#else
@:op(A >> B) private static function shr(a:Int32, b:Int32):Int32;
@:op(A >> B) private static function shrInt(a:Int32, b:Int):Int32;
@:op(A >> B) private static function intShr(a:Int, b:Int32):Int32;
#end
@:op(A >>> B) private static function ushr(a:Int32, b:Int32):Int32;
@:op(A >>> B) private static function ushrInt(a:Int32, b:Int):Int32;
@:op(A >>> B) private static function intUshr(a:Int, b:Int32):Int32;
#if (php || python || lua)
// PHP may be 64-bit, so shifts must be clamped
@:op(A << B) private static inline function shl(a:Int32, b:Int32):Int32
return clamp((a : Int) << (b : Int));
@:op(A << B) private static inline function shlInt(a:Int32, b:Int):Int32
return clamp((a : Int) << b);
@:op(A << B) private static inline function intShl(a:Int, b:Int32):Int32
return clamp(a << (b : Int));
#else
@:op(A << B) private static function shl(a:Int32, b:Int32):Int32;
@:op(A << B) private static function shlInt(a:Int32, b:Int):Int32;
@:op(A << B) private static function intShl(a:Int, b:Int32):Int32;
#end
@:to private inline function toFloat():Float
return this;
/**
Compare `a` and `b` in unsigned mode.
**/
public static function ucompare(a:Int32, b:Int32):Int {
if (a < 0)
return b < 0 ? (~b - ~a) : 1;
return b < 0 ? -1 : (a - b);
}
#if php
static var extraBits:Int = php.Const.PHP_INT_SIZE * 8 - 32;
#end
#if !lua
inline
#end
static function clamp(x:Int):Int {
// force to-int conversion on platforms that require it
#if js
return x | 0;
#elseif php
// we might be on 64-bit php, so sign extend from 32-bit
return (x << extraBits) >> extraBits;
#elseif python
return (python.Syntax.code("{0} % {1}", (x + python.Syntax.opPow(2, 31)), python.Syntax.opPow(2, 32)) : Int) - python.Syntax.opPow(2, 31);
#elseif lua
return lua.Boot.clampInt32(x);
#else
return (x);
#end
}
}

View File

@ -0,0 +1,485 @@
/*
* 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 haxe;
using haxe.Int64;
/**
A cross-platform signed 64-bit integer.
Int64 instances can be created from two 32-bit words using `Int64.make()`.
**/
#if flash
@:notNull
#end
@:transitive
abstract Int64(__Int64) from __Int64 to __Int64 {
private inline function new(x:__Int64)
this = x;
/**
Makes a copy of `this` Int64.
**/
public inline function copy():Int64
return make(high, low);
/**
Construct an Int64 from two 32-bit words `high` and `low`.
**/
public static inline function make(high:Int32, low:Int32):Int64
return new Int64(new __Int64(high, low));
/**
Returns an Int64 with the value of the Int `x`.
`x` is sign-extended to fill 64 bits.
**/
@:from public static inline function ofInt(x:Int):Int64
#if lua return make((x : Int32) >> 31, (x : Int32)); #else return make(x >> 31, x); #end
/**
Returns an Int with the value of the Int64 `x`.
Throws an exception if `x` cannot be represented in 32 bits.
**/
public static inline function toInt(x:Int64):Int {
if (x.high != x.low >> 31)
throw "Overflow";
return x.low;
}
@:deprecated('haxe.Int64.is() is deprecated. Use haxe.Int64.isInt64() instead')
inline public static function is(val:Dynamic):Bool {
return isInt64(val);
}
/**
Returns whether the value `val` is of type `haxe.Int64`
**/
inline public static function isInt64(val:Dynamic):Bool
return Std.isOfType(val, __Int64);
/**
Returns the high 32-bit word of `x`.
**/
@:deprecated("Use high instead")
public static inline function getHigh(x:Int64):Int32
return x.high;
/**
Returns the low 32-bit word of `x`.
**/
@:deprecated("Use low instead")
public static inline function getLow(x:Int64):Int32
return x.low;
/**
Returns `true` if `x` is less than zero.
**/
public static inline function isNeg(x:Int64):Bool
return x.high < 0;
/**
Returns `true` if `x` is exactly zero.
**/
public static inline function isZero(x:Int64):Bool
return x == 0;
/**
Compares `a` and `b` in signed mode.
Returns a negative value if `a < b`, positive if `a > b`,
or 0 if `a == b`.
**/
public static inline function compare(a:Int64, b:Int64):Int {
var v = a.high - b.high;
v = if (v != 0) v else Int32.ucompare(a.low, b.low);
return a.high < 0 ? (b.high < 0 ? v : -1) : (b.high >= 0 ? v : 1);
}
/**
Compares `a` and `b` in unsigned mode.
Returns a negative value if `a < b`, positive if `a > b`,
or 0 if `a == b`.
**/
public static inline function ucompare(a:Int64, b:Int64):Int {
var v = Int32.ucompare(a.high, b.high);
return if (v != 0) v else Int32.ucompare(a.low, b.low);
}
/**
Returns a signed decimal `String` representation of `x`.
**/
public static inline function toStr(x:Int64):String
return x.toString();
function toString():String {
var i:Int64 = cast this;
if (i == 0)
return "0";
var str = "";
var neg = false;
if (i.isNeg()) {
neg = true;
// i = -i; cannot negate here as --9223372036854775808 = -9223372036854775808
}
var ten:Int64 = 10;
while (i != 0) {
var r = i.divMod(ten);
if (r.modulus.isNeg()) {
str = Int64.neg(r.modulus).low + str;
i = Int64.neg(r.quotient);
} else {
str = r.modulus.low + str;
i = r.quotient;
}
}
if (neg)
str = "-" + str;
return str;
}
public static inline function parseString(sParam:String):Int64 {
return Int64Helper.parseString(sParam);
}
public static inline function fromFloat(f:Float):Int64 {
return Int64Helper.fromFloat(f);
}
/**
Performs signed integer divison of `dividend` by `divisor`.
Returns `{ quotient : Int64, modulus : Int64 }`.
**/
public static function divMod(dividend:Int64, divisor:Int64):{quotient:Int64, modulus:Int64} {
// Handle special cases of 0 and 1
if (divisor.high == 0) {
switch (divisor.low) {
case 0:
throw "divide by zero";
case 1:
return {quotient: dividend.copy(), modulus: 0};
}
}
var divSign = dividend.isNeg() != divisor.isNeg();
var modulus = dividend.isNeg() ? -dividend : dividend.copy();
divisor = divisor.isNeg() ? -divisor : divisor;
var quotient:Int64 = 0;
var mask:Int64 = 1;
while (!divisor.isNeg()) {
var cmp = ucompare(divisor, modulus);
divisor <<= 1;
mask <<= 1;
if (cmp >= 0)
break;
}
while (mask != 0) {
if (ucompare(modulus, divisor) >= 0) {
quotient |= mask;
modulus -= divisor;
}
mask >>>= 1;
divisor >>>= 1;
}
if (divSign)
quotient = -quotient;
if (dividend.isNeg())
modulus = -modulus;
return {
quotient: quotient,
modulus: modulus
};
}
/**
Returns the negative of `x`.
**/
@:op(-A) public static inline function neg(x:Int64):Int64 {
var high = ~x.high;
var low = -x.low;
if (low == 0)
high++;
return make(high, low);
}
@:op(++A) private inline function preIncrement():Int64 {
this = copy();
this.low++;
if (this.low == 0)
this.high++;
return cast this;
}
@:op(A++) private inline function postIncrement():Int64 {
var ret = this;
preIncrement();
return ret;
}
@:op(--A) private inline function preDecrement():Int64 {
this = copy();
if (this.low == 0)
this.high--;
this.low--;
return cast this;
}
@:op(A--) private inline function postDecrement():Int64 {
var ret = this;
preDecrement();
return ret;
}
/**
Returns the sum of `a` and `b`.
**/
@:op(A + B) public static inline function add(a:Int64, b:Int64):Int64 {
var high = a.high + b.high;
var low = a.low + b.low;
if (Int32.ucompare(low, a.low) < 0)
high++;
return make(high, low);
}
@:op(A + B) @:commutative private static inline function addInt(a:Int64, b:Int):Int64
return add(a, b);
/**
Returns `a` minus `b`.
**/
@:op(A - B) public static inline function sub(a:Int64, b:Int64):Int64 {
var high = a.high - b.high;
var low = a.low - b.low;
if (Int32.ucompare(a.low, b.low) < 0)
high--;
return make(high, low);
}
@:op(A - B) private static inline function subInt(a:Int64, b:Int):Int64
return sub(a, b);
@:op(A - B) private static inline function intSub(a:Int, b:Int64):Int64
return sub(a, b);
/**
Returns the product of `a` and `b`.
**/
@:op(A * B)
public static #if !lua inline #end function mul(a:Int64, b:Int64):Int64 {
var mask = 0xFFFF;
var al = a.low & mask, ah = a.low >>> 16;
var bl = b.low & mask, bh = b.low >>> 16;
var p00 = al * bl;
var p10 = ah * bl;
var p01 = al * bh;
var p11 = ah * bh;
var low = p00;
var high = p11 + (p01 >>> 16) + (p10 >>> 16);
p01 <<= 16;
low += p01;
if (Int32.ucompare(low, p01) < 0)
high++;
p10 <<= 16;
low += p10;
if (Int32.ucompare(low, p10) < 0)
high++;
high += a.low * b.high + a.high * b.low;
return make(high, low);
}
@:op(A * B) @:commutative private static inline function mulInt(a:Int64, b:Int):Int64
return mul(a, b);
/**
Returns the quotient of `a` divided by `b`.
**/
@:op(A / B) public static inline function div(a:Int64, b:Int64):Int64
return divMod(a, b).quotient;
@:op(A / B) private static inline function divInt(a:Int64, b:Int):Int64
return div(a, b);
@:op(A / B) private static inline function intDiv(a:Int, b:Int64):Int64
return div(a, b).toInt();
/**
Returns the modulus of `a` divided by `b`.
**/
@:op(A % B) public static inline function mod(a:Int64, b:Int64):Int64
return divMod(a, b).modulus;
@:op(A % B) private static inline function modInt(a:Int64, b:Int):Int64
return mod(a, b).toInt();
@:op(A % B) private static inline function intMod(a:Int, b:Int64):Int64
return mod(a, b).toInt();
/**
Returns `true` if `a` is equal to `b`.
**/
@:op(A == B) public static inline function eq(a:Int64, b:Int64):Bool
return a.high == b.high && a.low == b.low;
@:op(A == B) @:commutative private static inline function eqInt(a:Int64, b:Int):Bool
return eq(a, b);
/**
Returns `true` if `a` is not equal to `b`.
**/
@:op(A != B) public static inline function neq(a:Int64, b:Int64):Bool
return a.high != b.high || a.low != b.low;
@:op(A != B) @:commutative private static inline function neqInt(a:Int64, b:Int):Bool
return neq(a, b);
@:op(A < B) private static inline function lt(a:Int64, b:Int64):Bool
return compare(a, b) < 0;
@:op(A < B) private static inline function ltInt(a:Int64, b:Int):Bool
return lt(a, b);
@:op(A < B) private static inline function intLt(a:Int, b:Int64):Bool
return lt(a, b);
@:op(A <= B) private static inline function lte(a:Int64, b:Int64):Bool
return compare(a, b) <= 0;
@:op(A <= B) private static inline function lteInt(a:Int64, b:Int):Bool
return lte(a, b);
@:op(A <= B) private static inline function intLte(a:Int, b:Int64):Bool
return lte(a, b);
@:op(A > B) private static inline function gt(a:Int64, b:Int64):Bool
return compare(a, b) > 0;
@:op(A > B) private static inline function gtInt(a:Int64, b:Int):Bool
return gt(a, b);
@:op(A > B) private static inline function intGt(a:Int, b:Int64):Bool
return gt(a, b);
@:op(A >= B) private static inline function gte(a:Int64, b:Int64):Bool
return compare(a, b) >= 0;
@:op(A >= B) private static inline function gteInt(a:Int64, b:Int):Bool
return gte(a, b);
@:op(A >= B) private static inline function intGte(a:Int, b:Int64):Bool
return gte(a, b);
/**
Returns the bitwise NOT of `a`.
**/
@:op(~A) private static inline function complement(a:Int64):Int64
return make(~a.high, ~a.low);
/**
Returns the bitwise AND of `a` and `b`.
**/
@:op(A & B) public static inline function and(a:Int64, b:Int64):Int64
return make(a.high & b.high, a.low & b.low);
/**
Returns the bitwise OR of `a` and `b`.
**/
@:op(A | B) public static inline function or(a:Int64, b:Int64):Int64
return make(a.high | b.high, a.low | b.low);
/**
Returns the bitwise XOR of `a` and `b`.
**/
@:op(A ^ B) public static inline function xor(a:Int64, b:Int64):Int64
return make(a.high ^ b.high, a.low ^ b.low);
/**
Returns `a` left-shifted by `b` bits.
**/
@:op(A << B) public static inline function shl(a:Int64, b:Int):Int64 {
b &= 63;
return if (b == 0) a.copy() else if (b < 32) make((a.high << b) | (a.low >>> (32 - b)), a.low << b) else make(a.low << (b - 32), 0);
}
/**
Returns `a` right-shifted by `b` bits in signed mode.
`a` is sign-extended.
**/
@:op(A >> B) public static inline function shr(a:Int64, b:Int):Int64 {
b &= 63;
return if (b == 0) a.copy() else if (b < 32) make(a.high >> b, (a.high << (32 - b)) | (a.low >>> b)); else make(a.high >> 31, a.high >> (b - 32));
}
/**
Returns `a` right-shifted by `b` bits in unsigned mode.
`a` is padded with zeroes.
**/
@:op(A >>> B) public static inline function ushr(a:Int64, b:Int):Int64 {
b &= 63;
return if (b == 0) a.copy() else if (b < 32) make(a.high >>> b, (a.high << (32 - b)) | (a.low >>> b)); else make(0, a.high >>> (b - 32));
}
public var high(get, never):Int32;
private inline function get_high()
return this.high;
private inline function set_high(x)
return this.high = x;
public var low(get, never):Int32;
private inline function get_low()
return this.low;
private inline function set_low(x)
return this.low = x;
}
/**
This typedef will fool `@:coreApi` into thinking that we are using
the same underlying type, even though it might be different on
specific platforms.
**/
private typedef __Int64 = ___Int64;
private class ___Int64 {
public var high:Int32;
public var low:Int32;
public inline function new(high, low) {
this.high = high;
this.low = low;
}
/**
We also define toString here to ensure we always get a pretty string
when tracing or calling `Std.string`. This tends not to happen when
`toString` is only in the abstract.
**/
public function toString():String
return Int64.toStr(cast this);
}

View File

@ -0,0 +1,116 @@
/*
* 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 haxe;
using haxe.Int64;
import StringTools;
/**
Helper for parsing to `Int64` instances.
**/
class Int64Helper {
/**
Create `Int64` from given string.
**/
public static function parseString(sParam:String):Int64 {
var base = Int64.ofInt(10);
var current = Int64.ofInt(0);
var multiplier = Int64.ofInt(1);
var sIsNegative = false;
var s = StringTools.trim(sParam);
if (s.charAt(0) == "-") {
sIsNegative = true;
s = s.substring(1, s.length);
}
var len = s.length;
for (i in 0...len) {
var digitInt = s.charCodeAt(len - 1 - i) - '0'.code;
if (digitInt < 0 || digitInt > 9) {
throw "NumberFormatError";
}
if (digitInt != 0) {
var digit:Int64 = Int64.ofInt(digitInt);
if (sIsNegative) {
current = Int64.sub(current, Int64.mul(multiplier, digit));
if (!Int64.isNeg(current)) {
throw "NumberFormatError: Underflow";
}
} else {
current = Int64.add(current, Int64.mul(multiplier, digit));
if (Int64.isNeg(current)) {
throw "NumberFormatError: Overflow";
}
}
}
multiplier = Int64.mul(multiplier, base);
}
return current;
}
/**
Create `Int64` from given float.
**/
public static function fromFloat(f:Float):Int64 {
if (Math.isNaN(f) || !Math.isFinite(f)) {
throw "Number is NaN or Infinite";
}
var noFractions = f - (f % 1);
// 2^53-1 and -2^53+1: these are parseable without loss of precision.
// In theory 2^53 and -2^53 are parseable too, but then there's no way to
// distinguish 2^53 from 2^53+1
// (i.e. trace(9007199254740992. + 1. > 9007199254740992.); // false!)
if (noFractions > 9007199254740991) {
throw "Conversion overflow";
}
if (noFractions < -9007199254740991) {
throw "Conversion underflow";
}
var result = Int64.ofInt(0);
var neg = noFractions < 0;
var rest = neg ? -noFractions : noFractions;
var i = 0;
while (rest >= 1) {
var curr = rest % 2;
rest = rest / 2;
if (curr >= 1) {
result = Int64.add(result, Int64.shl(Int64.ofInt(1), i));
}
i++;
}
if (neg) {
result = Int64.neg(result);
}
return result;
}
}

View File

@ -0,0 +1,62 @@
/*
* 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 haxe;
/**
Cross-platform JSON API: it will automatically use the optimized native API if available.
Use `-D haxeJSON` to force usage of the Haxe implementation even if a native API is found:
This will provide extra encoding features such as enums (replaced by their index) and StringMaps.
@see https://haxe.org/manual/std-Json.html
**/
class Json {
/**
Parses given JSON-encoded `text` and returns the resulting object.
JSON objects are parsed into anonymous structures and JSON arrays
are parsed into `Array<Dynamic>`.
If given `text` is not valid JSON, an exception will be thrown.
@see https://haxe.org/manual/std-Json-parsing.html
**/
public static inline function parse(text:String):Dynamic {
return haxe.format.JsonParser.parse(text);
}
/**
Encodes the given `value` and returns the resulting JSON string.
If `replacer` is given and is not null, it is used to retrieve the
actual object to be encoded. The `replacer` function takes two parameters,
the key and the value being encoded. Initial key value is an empty string.
If `space` is given and is not null, the result will be pretty-printed.
Successive levels will be indented by this string.
@see https://haxe.org/manual/std-Json-encoding.html
**/
public static inline function stringify(value:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String):String {
return haxe.format.JsonPrinter.print(value, replacer, space);
}
}

View File

@ -0,0 +1,75 @@
/*
* 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 haxe;
/**
Log primarily provides the `trace()` method, which is invoked upon a call to
`trace()` in Haxe code.
**/
class Log {
/**
Format the output of `trace` before printing it.
**/
public static function formatOutput(v:Dynamic, infos:PosInfos):String {
var str = Std.string(v);
if (infos == null)
return str;
var pstr = infos.fileName + ":" + infos.lineNumber;
if (infos.customParams != null)
for (v in infos.customParams)
str += ", " + Std.string(v);
return pstr + ": " + str;
}
/**
Outputs `v` in a platform-dependent way.
The second parameter `infos` is injected by the compiler and contains
information about the position where the `trace()` call was made.
This method can be rebound to a custom function:
var oldTrace = haxe.Log.trace; // store old function
haxe.Log.trace = function(v, ?infos) {
// handle trace
}
...
haxe.Log.trace = oldTrace;
If it is bound to null, subsequent calls to `trace()` will cause an
exception.
**/
public static dynamic function trace(v:Dynamic, ?infos:PosInfos):Void {
var str = formatOutput(v, infos);
#if js
if (js.Syntax.typeof(untyped console) != "undefined" && (untyped console).log != null)
(untyped console).log(str);
#elseif lua
untyped __define_feature__("use._hx_print", _hx_print(str));
#elseif sys
Sys.println(str);
#else
throw new haxe.exceptions.NotImplementedException()
#end
}
}

View File

@ -0,0 +1,211 @@
package haxe;
import haxe.EntryPoint;
#if (target.threaded && !cppia)
import sys.thread.EventLoop;
import sys.thread.Thread;
#end
class MainEvent {
var f:Void->Void;
var prev:MainEvent;
var next:MainEvent;
/**
Tells if the event can lock the process from exiting (default:true)
**/
public var isBlocking:Bool = true;
public var nextRun(default, null):Float;
public var priority(default, null):Int;
function new(f, p) {
this.f = f;
this.priority = p;
nextRun = Math.NEGATIVE_INFINITY;
}
/**
Delay the execution of the event for the given time, in seconds.
If t is null, the event will be run at tick() time.
**/
public function delay(t:Null<Float>) {
nextRun = t == null ? Math.NEGATIVE_INFINITY : haxe.Timer.stamp() + t;
}
/**
Call the event. Will do nothing if the event has been stopped.
**/
public inline function call() {
if (f != null)
f();
}
/**
Stop the event from firing anymore.
**/
public function stop() {
if (f == null)
return;
f = null;
nextRun = Math.NEGATIVE_INFINITY;
if (prev == null)
@:privateAccess MainLoop.pending = next;
else
prev.next = next;
if (next != null)
next.prev = prev;
}
}
@:access(haxe.MainEvent)
class MainLoop {
#if (target.threaded && !cppia)
static var eventLoopHandler:Null<EventHandler>;
static var mutex = new sys.thread.Mutex();
static var mainThread = Thread.current();
#end
static var pending:MainEvent;
public static var threadCount(get, never):Int;
inline static function get_threadCount()
return EntryPoint.threadCount;
public static function hasEvents() {
var p = pending;
while (p != null) {
if (p.isBlocking)
return true;
p = p.next;
}
return false;
}
public static function addThread(f:Void->Void) {
EntryPoint.addThread(f);
}
public static function runInMainThread(f:Void->Void) {
EntryPoint.runInMainThread(f);
}
/**
Add a pending event to be run into the main loop.
**/
public static function add(f:Void->Void, priority = 0):MainEvent@:privateAccess {
if (f == null)
throw "Event function is null";
var e = new MainEvent(f, priority);
var head = pending;
if (head != null)
head.prev = e;
e.next = head;
pending = e;
injectIntoEventLoop(0);
return e;
}
static function injectIntoEventLoop(waitMs:Int) {
#if (target.threaded && !cppia)
mutex.acquire();
if(eventLoopHandler != null)
mainThread.events.cancel(eventLoopHandler);
eventLoopHandler = mainThread.events.repeat(
() -> {
mainThread.events.cancel(eventLoopHandler);
var wait = tick();
if(hasEvents()) {
injectIntoEventLoop(Std.int(wait * 1000));
}
},
waitMs
);
mutex.release();
#end
}
static function sortEvents() {
// pending = haxe.ds.ListSort.sort(pending, function(e1, e2) return e1.nextRun > e2.nextRun ? -1 : 1);
// we can't use directly ListSort because it requires prev/next to be public, which we don't want here
// we do then a manual inline, this also allow use to do a Float comparison of nextRun
var list = pending;
if (list == null)
return;
var insize = 1, nmerges, psize = 0, qsize = 0;
var p, q, e, tail:MainEvent;
while (true) {
p = list;
list = null;
tail = null;
nmerges = 0;
while (p != null) {
nmerges++;
q = p;
psize = 0;
for (i in 0...insize) {
psize++;
q = q.next;
if (q == null)
break;
}
qsize = insize;
while (psize > 0 || (qsize > 0 && q != null)) {
if (psize == 0) {
e = q;
q = q.next;
qsize--;
} else if (qsize == 0
|| q == null
|| (p.priority > q.priority || (p.priority == q.priority && p.nextRun <= q.nextRun))) {
e = p;
p = p.next;
psize--;
} else {
e = q;
q = q.next;
qsize--;
}
if (tail != null)
tail.next = e;
else
list = e;
e.prev = tail;
tail = e;
}
p = q;
}
tail.next = null;
if (nmerges <= 1)
break;
insize *= 2;
}
list.prev = null; // not cycling
pending = list;
}
/**
Run the pending events. Return the time for next event.
**/
static function tick() {
sortEvents();
var e = pending;
var now = haxe.Timer.stamp();
var wait = 1e9;
while (e != null) {
var next = e.next;
var wt = e.nextRun - now;
if (wt <= 0) {
wait = 0;
e.call();
} else if (wait > wt)
wait = wt;
e = next;
}
return wait;
}
}

View File

@ -0,0 +1,15 @@
package haxe;
import haxe.CallStack.StackItem;
/**
Do not use manually.
**/
@:dox(hide)
@:noCompletion
extern class NativeStackTrace {
static public function saveStack(exception:Any):Void;
static public function callStack():Any;
static public function exceptionStack():Any;
static public function toHaxe(nativeStackTrace:Any, skip:Int = 0):Array<StackItem>;
}

View File

@ -0,0 +1,42 @@
/*
* 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 haxe;
/**
`PosInfos` is a magic type which can be used to generate position information
into the output for debugging use.
If a function has a final optional argument of this type, i.e.
`(..., ?pos:haxe.PosInfos)`, each call to that function which does not assign
a value to that argument has its position added as call argument.
This can be used to track positions of calls in e.g. a unit testing
framework.
**/
typedef PosInfos = {
var fileName:String;
var lineNumber:Int;
var className:String;
var methodName:String;
var ?customParams:Array<Dynamic>;
}

View File

@ -0,0 +1,80 @@
/*
* 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 haxe;
/**
Resource can be used to access resources that were added through the
`--resource file@name` command line parameter.
Depending on their type they can be obtained as `String` through
`getString(name)`, or as binary data through `getBytes(name)`.
A list of all available resource names can be obtained from `listNames()`.
**/
class Resource {
static var content:Array<{name:String, data:String, str:String}>;
/**
Lists all available resource names. The resource name is the name part
of the `--resource file@name` command line parameter.
**/
public static function listNames():Array<String> {
return [for (x in content) x.name];
}
/**
Retrieves the resource identified by `name` as a `String`.
If `name` does not match any resource name, `null` is returned.
**/
public static function getString(name:String):String {
for (x in content)
if (x.name == name) {
if (x.str != null)
return x.str;
var b:haxe.io.Bytes = haxe.crypto.Base64.decode(x.data);
return b.toString();
}
return null;
}
/**
Retrieves the resource identified by `name` as an instance of
haxe.io.Bytes.
If `name` does not match any resource name, `null` is returned.
**/
public static function getBytes(name:String):haxe.io.Bytes {
for (x in content)
if (x.name == name) {
if (x.str != null)
return haxe.io.Bytes.ofString(x.str);
return haxe.crypto.Base64.decode(x.data);
}
return null;
}
static function __init__() {
content = untyped __resources__();
}
}

View File

@ -0,0 +1,91 @@
package haxe;
import haxe.iterators.RestIterator;
import haxe.iterators.RestKeyValueIterator;
private typedef NativeRest<T> = Array<T>;
/**
A special type that represents a "rest" function argument.
The special `...` syntax can be used for convenience and improved readability:
```haxe
function f(...rest:Int) {
$type(rest); // haxe.Rest<Int>
}
f(1, 2, 3);
final array = [1, 2, 3];
f(...array);
```
Should be used as a type for the last argument of a method, indicating that
an arbitrary number of arguments of the given type can be passed to that method.
Allows to use array access by index to get values of rest arguments.
If the index exceeds the amount of rest arguments passed, the result is unspecified.
**/
@:coreApi
abstract Rest<T>(NativeRest<T>) {
/** Amount of arguments passed as rest arguments */
public var length(get,never):Int;
inline function get_length():Int
return this.length;
/**
Create rest arguments using contents of `array`.
WARNING:
Depending on a target platform modifying `array` after using this method
may affect the created `Rest` instance.
Use `Rest.of(array.copy())` to avoid that.
**/
@:from static public inline function of<T>(array:Array<T>):Rest<T>
return new Rest(array);
inline function new(array:Array<T>):Void
this = array;
@:arrayAccess inline function get(index:Int):T
return this[index];
/**
Creates an array containing all the values of rest arguments.
**/
@:to public #if !cppia inline #end function toArray():Array<T>
return this.copy();
public inline function iterator():RestIterator<T>
return new RestIterator<T>(this);
public inline function keyValueIterator():RestKeyValueIterator<T>
return new RestKeyValueIterator<T>(this);
/**
Create a new rest arguments collection by appending `item` to this one.
**/
public function append(item:T):Rest<T> {
var result = this.copy();
result.push(item);
return new Rest(result);
}
/**
Create a new rest arguments collection by prepending this one with `item`.
**/
public function prepend(item:T):Rest<T> {
var result = this.copy();
result.unshift(item);
return new Rest(result);
}
public inline function toString():String {
#if (flash || js)
return '[${this.toString()}]';
#else
return this.toString();
#end
}
}

View File

@ -0,0 +1,591 @@
/*
* 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 haxe;
import haxe.ds.List;
/**
The Serializer class can be used to encode values and objects into a `String`,
from which the `Unserializer` class can recreate the original representation.
This class can be used in two ways:
- create a `new Serializer()` instance, call its `serialize()` method with
any argument and finally retrieve the String representation from
`toString()`
- call `Serializer.run()` to obtain the serialized representation of a
single argument
Serialization is guaranteed to work for all haxe-defined classes, but may
or may not work for instances of external/native classes.
The specification of the serialization format can be found here:
<https://haxe.org/manual/std-serialization-format.html>
**/
class Serializer {
/**
If the values you are serializing can contain circular references or
objects repetitions, you should set `USE_CACHE` to true to prevent
infinite loops.
This may also reduce the size of serialization Strings at the expense of
performance.
This value can be changed for individual instances of `Serializer` by
setting their `useCache` field.
**/
public static var USE_CACHE = false;
/**
Use constructor indexes for enums instead of names.
This may reduce the size of serialization Strings, but makes them less
suited for long-term storage: If constructors are removed or added from
the enum, the indices may no longer match.
This value can be changed for individual instances of `Serializer` by
setting their `useEnumIndex` field.
**/
public static var USE_ENUM_INDEX = false;
static var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%:";
static var BASE64_CODES = null;
var buf:StringBuf;
var cache:Array<Dynamic>;
var shash:haxe.ds.StringMap<Int>;
var scount:Int;
/**
The individual cache setting for `this` Serializer instance.
See `USE_CACHE` for a complete description.
**/
public var useCache:Bool;
/**
The individual enum index setting for `this` Serializer instance.
See `USE_ENUM_INDEX` for a complete description.
**/
public var useEnumIndex:Bool;
/**
Creates a new Serializer instance.
Subsequent calls to `this.serialize` will append values to the
internal buffer of this String. Once complete, the contents can be
retrieved through a call to `this.toString`.
Each `Serializer` instance maintains its own cache if `this.useCache` is
`true`.
**/
public function new() {
buf = new StringBuf();
cache = new Array();
useCache = USE_CACHE;
useEnumIndex = USE_ENUM_INDEX;
shash = new haxe.ds.StringMap();
scount = 0;
}
/**
Return the String representation of `this` Serializer.
The exact format specification can be found here:
https://haxe.org/manual/serialization/format
**/
public function toString() {
return buf.toString();
}
/* prefixes :
a : array
b : hash
c : class
d : Float
e : reserved (float exp)
f : false
g : object end
h : array/list/hash end
i : Int
j : enum (by index)
k : NaN
l : list
m : -Inf
n : null
o : object
p : +Inf
q : haxe.ds.IntMap
r : reference
s : bytes (base64)
t : true
u : array nulls
v : date
w : enum
x : exception
y : urlencoded string
z : zero
A : Class<Dynamic>
B : Enum<Dynamic>
M : haxe.ds.ObjectMap
C : custom
*/
function serializeString(s:String) {
var x = shash.get(s);
if (x != null) {
buf.add("R");
buf.add(x);
return;
}
shash.set(s, scount++);
#if old_serialize
// no more support for -D old_serialize due to 'j' reuse
#if error
#end
#end
buf.add("y");
s = StringTools.urlEncode(s);
buf.add(s.length);
buf.add(":");
buf.add(s);
}
function serializeRef(v:Dynamic) {
#if js
var vt = js.Syntax.typeof(v);
#end
for (i in 0...cache.length) {
#if js
var ci = cache[i];
if (js.Syntax.typeof(ci) == vt && ci == v) {
#else
if (cache[i] == v) {
#end
buf.add("r");
buf.add(i);
return true;
}
}
cache.push(v);
return false;
}
#if flash
// only the instance variables
function serializeClassFields(v:Dynamic, c:Dynamic) {
var xml:flash.xml.XML = untyped __global__["flash.utils.describeType"](c);
var vars = xml.factory[0].child("variable");
for (i in 0...vars.length()) {
var f = vars[i].attribute("name").toString();
if (!v.hasOwnProperty(f))
continue;
serializeString(f);
serialize(Reflect.field(v, f));
}
buf.add("g");
}
#end
function serializeFields(v:{}) {
for (f in Reflect.fields(v)) {
serializeString(f);
serialize(Reflect.field(v, f));
}
buf.add("g");
}
/**
Serializes `v`.
All haxe-defined values and objects with the exception of functions can
be serialized. Serialization of external/native objects is not
guaranteed to work.
The values of `this.useCache` and `this.useEnumIndex` may affect
serialization output.
**/
public function serialize(v:Dynamic) {
switch (Type.typeof(v)) {
case TNull:
buf.add("n");
case TInt:
var v:Int = v;
if (v == 0) {
buf.add("z");
return;
}
buf.add("i");
buf.add(v);
case TFloat:
var v:Float = v;
if (Math.isNaN(v))
buf.add("k");
else if (!Math.isFinite(v))
buf.add(if (v < 0) "m" else "p");
else {
buf.add("d");
buf.add(v);
}
case TBool:
buf.add(if (v) "t" else "f");
case TClass(c):
if (#if neko untyped c.__is_String #else c == String #end) {
serializeString(v);
return;
}
if (useCache && serializeRef(v))
return;
switch (#if (neko || cs || python) Type.getClassName(c) #else c #end) {
case #if (neko || cs || python) "Array" #else cast Array #end:
var ucount = 0;
buf.add("a");
#if (flash || python || hl)
var v:Array<Dynamic> = v;
#end
var l = #if (neko || flash || php || cs || java || python || hl || lua || eval) v.length #elseif cpp v.__length() #else __getField(v,
"length") #end;
for (i in 0...l) {
if (v[i] == null)
ucount++;
else {
if (ucount > 0) {
if (ucount == 1)
buf.add("n");
else {
buf.add("u");
buf.add(ucount);
}
ucount = 0;
}
serialize(v[i]);
}
}
if (ucount > 0) {
if (ucount == 1)
buf.add("n");
else {
buf.add("u");
buf.add(ucount);
}
}
buf.add("h");
case #if (neko || cs || python) "haxe.ds.List" #else cast List #end:
buf.add("l");
var v:List<Dynamic> = v;
for (i in v)
serialize(i);
buf.add("h");
case #if (neko || cs || python) "Date" #else cast Date #end:
var d:Date = v;
buf.add("v");
buf.add(d.getTime());
case #if (neko || cs || python) "haxe.ds.StringMap" #else cast haxe.ds.StringMap #end:
buf.add("b");
var v:haxe.ds.StringMap<Dynamic> = v;
for (k in v.keys()) {
serializeString(k);
serialize(v.get(k));
}
buf.add("h");
case #if (neko || cs || python) "haxe.ds.IntMap" #else cast haxe.ds.IntMap #end:
buf.add("q");
var v:haxe.ds.IntMap<Dynamic> = v;
for (k in v.keys()) {
buf.add(":");
buf.add(k);
serialize(v.get(k));
}
buf.add("h");
case #if (neko || cs || python) "haxe.ds.ObjectMap" #else cast haxe.ds.ObjectMap #end:
buf.add("M");
var v:haxe.ds.ObjectMap<Dynamic, Dynamic> = v;
for (k in v.keys()) {
#if (js || neko)
var id = Reflect.field(k, "__id__");
Reflect.deleteField(k, "__id__");
serialize(k);
Reflect.setField(k, "__id__", id);
#else
serialize(k);
#end
serialize(v.get(k));
}
buf.add("h");
case #if (neko || cs || python) "haxe.io.Bytes" #else cast haxe.io.Bytes #end:
var v:haxe.io.Bytes = v;
#if neko
var chars = new String(base_encode(v.getData(), untyped BASE64.__s));
buf.add("s");
buf.add(chars.length);
buf.add(":");
buf.add(chars);
#elseif php
var chars = new String(php.Global.base64_encode(v.getData()));
chars = php.Global.strtr(chars, '+/', '%:');
buf.add("s");
buf.add(chars.length);
buf.add(":");
buf.add(chars);
#else
buf.add("s");
buf.add(Math.ceil((v.length * 8) / 6));
buf.add(":");
var i = 0;
var max = v.length - 2;
var b64 = BASE64_CODES;
if (b64 == null) {
b64 = new haxe.ds.Vector(BASE64.length);
for (i in 0...BASE64.length)
b64[i] = BASE64.charCodeAt(i);
BASE64_CODES = b64;
}
while (i < max) {
var b1 = v.get(i++);
var b2 = v.get(i++);
var b3 = v.get(i++);
buf.addChar(b64[b1 >> 2]);
buf.addChar(b64[((b1 << 4) | (b2 >> 4)) & 63]);
buf.addChar(b64[((b2 << 2) | (b3 >> 6)) & 63]);
buf.addChar(b64[b3 & 63]);
}
if (i == max) {
var b1 = v.get(i++);
var b2 = v.get(i++);
buf.addChar(b64[b1 >> 2]);
buf.addChar(b64[((b1 << 4) | (b2 >> 4)) & 63]);
buf.addChar(b64[(b2 << 2) & 63]);
} else if (i == max + 1) {
var b1 = v.get(i++);
buf.addChar(b64[b1 >> 2]);
buf.addChar(b64[(b1 << 4) & 63]);
}
#end
default:
if (useCache) cache.pop();
if (#if flash try
v.hxSerialize != null
catch (e:Dynamic)
false #elseif (cs || java || python) Reflect.hasField(v,
"hxSerialize") #elseif php php.Global.method_exists(v, 'hxSerialize') #else v.hxSerialize != null #end) {
buf.add("C");
serializeString(Type.getClassName(c));
if (useCache)
cache.push(v);
v.hxSerialize(this);
buf.add("g");
} else {
buf.add("c");
serializeString(Type.getClassName(c));
if (useCache)
cache.push(v);
#if flash
serializeClassFields(v, c);
#else
serializeFields(v);
#end
}
}
case TObject:
if (Std.isOfType(v, Class)) {
var className = Type.getClassName(v);
#if (flash || cpp)
// Currently, Enum and Class are the same for flash and cpp.
// use resolveEnum to test if it is actually an enum
if (Type.resolveEnum(className) != null)
buf.add("B")
else
#end
buf.add("A");
serializeString(className);
} else if (Std.isOfType(v, Enum)) {
buf.add("B");
serializeString(Type.getEnumName(v));
} else {
if (useCache && serializeRef(v))
return;
buf.add("o");
serializeFields(v);
}
case TEnum(e):
if (useCache) {
if (serializeRef(v))
return;
cache.pop();
}
buf.add(useEnumIndex ? "j" : "w");
serializeString(Type.getEnumName(e));
#if neko
if (useEnumIndex) {
buf.add(":");
buf.add(v.index);
} else
serializeString(new String(v.tag));
buf.add(":");
if (v.args == null)
buf.add(0);
else {
var l:Int = untyped __dollar__asize(v.args);
buf.add(l);
for (i in 0...l)
serialize(v.args[i]);
}
#elseif flash
if (useEnumIndex) {
buf.add(":");
var i:Int = v.index;
buf.add(i);
} else
serializeString(v.tag);
buf.add(":");
var pl:Array<Dynamic> = v.params;
if (pl == null)
buf.add(0);
else {
buf.add(pl.length);
for (p in pl)
serialize(p);
}
#elseif cpp
var enumBase:cpp.EnumBase = v;
if (useEnumIndex) {
buf.add(":");
buf.add(enumBase.getIndex());
} else
serializeString(enumBase.getTag());
buf.add(":");
var len = enumBase.getParamCount();
buf.add(len);
for (p in 0...len)
serialize(enumBase.getParamI(p));
#elseif php
if (useEnumIndex) {
buf.add(":");
buf.add(v.index);
} else
serializeString(v.tag);
buf.add(":");
var l:Int = php.Syntax.code("count({0})", v.params);
if (l == 0 || v.params == null)
buf.add(0);
else {
buf.add(l);
for (i in 0...l) {
#if php
serialize(v.params[i]);
#end
}
}
#elseif (java || cs || python || hl || eval)
if (useEnumIndex) {
buf.add(":");
buf.add(Type.enumIndex(v));
} else
serializeString(Type.enumConstructor(v));
buf.add(":");
var arr:Array<Dynamic> = Type.enumParameters(v);
if (arr != null) {
buf.add(arr.length);
for (v in arr)
serialize(v);
} else {
buf.add("0");
}
#elseif (js && !js_enums_as_arrays)
if (useEnumIndex) {
buf.add(":");
buf.add(v._hx_index);
} else
serializeString(Type.enumConstructor(v));
buf.add(":");
var params = Type.enumParameters(v);
buf.add(params.length);
for (p in params)
serialize(p);
#else
if (useEnumIndex) {
buf.add(":");
buf.add(v[1]);
} else
serializeString(v[0]);
buf.add(":");
var l = __getField(v, "length");
buf.add(l - 2);
for (i in 2...l)
serialize(v[i]);
#end
if (useCache)
cache.push(v);
case TFunction:
throw "Cannot serialize function";
default:
#if neko
if (untyped (__i32__kind != null && __dollar__iskind(v, __i32__kind))) {
buf.add("i");
buf.add(v);
return;
}
#end
throw "Cannot serialize " + Std.string(v);
}
}
extern inline function __getField(o:Dynamic, f:String):Dynamic
return o[cast f];
public function serializeException(e:Dynamic) {
buf.add("x");
#if flash
if (untyped __is__(e, __global__["Error"])) {
var e:flash.errors.Error = e;
var s = e.getStackTrace();
if (s == null)
serialize(e.message);
else
serialize(s);
return;
}
#end
serialize(e);
}
/**
Serializes `v` and returns the String representation.
This is a convenience function for creating a new instance of
Serializer, serialize `v` into it and obtain the result through a call
to `toString()`.
**/
public static function run(v:Dynamic) {
var s = new Serializer();
s.serialize(v);
return s.toString();
}
#if neko
static var base_encode = neko.Lib.load("std", "base_encode", 2);
#end
}

View File

@ -0,0 +1,106 @@
package haxe;
import haxe.ds.ReadOnlyArray;
class SysTools {
/**
Character codes of the characters that will be escaped by `quoteWinArg(_, true)`.
**/
public static final winMetaCharacters:ReadOnlyArray<Int> = [
" ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code, ",".code, ";".code
];
/**
Returns a String that can be used as a single command line argument
on Unix.
The input will be quoted, or escaped if necessary.
**/
public static function quoteUnixArg(argument:String):String {
// Based on cpython's shlex.quote().
// https://hg.python.org/cpython/file/a3f076d4f54f/Lib/shlex.py#l278
if (argument == "")
return "''";
if (!~/[^a-zA-Z0-9_@%+=:,.\/-]/.match(argument))
return argument;
// use single quotes, and put single quotes into double quotes
// the string $'b is then quoted as '$'"'"'b'
return "'" + StringTools.replace(argument, "'", "'\"'\"'") + "'";
}
/**
Returns a String that can be used as a single command line argument
on Windows.
The input will be quoted, or escaped if necessary, such that the output
will be parsed as a single argument using the rule specified in
http://msdn.microsoft.com/en-us/library/ms880421
Examples:
```haxe
quoteWinArg("abc") == "abc";
quoteWinArg("ab c") == '"ab c"';
```
**/
public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String {
// If there is no space, tab, back-slash, or double-quotes, and it is not an empty string.
if (!~/^[^ \t\\"]+$/.match(argument)) {
// Based on cpython's subprocess.list2cmdline().
// https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620
var result = new StringBuf();
var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == "";
if (needquote)
result.add('"');
var bs_buf = new StringBuf();
for (i in 0...argument.length) {
switch (argument.charCodeAt(i)) {
case "\\".code:
// Don't know if we need to double yet.
bs_buf.add("\\");
case '"'.code:
// Double backslashes.
var bs = bs_buf.toString();
result.add(bs);
result.add(bs);
bs_buf = new StringBuf();
result.add('\\"');
case var c:
// Normal char
if (bs_buf.length > 0) {
result.add(bs_buf.toString());
bs_buf = new StringBuf();
}
result.addChar(c);
}
}
// Add remaining backslashes, if any.
result.add(bs_buf.toString());
if (needquote) {
result.add(bs_buf.toString());
result.add('"');
}
argument = result.toString();
}
if (escapeMetaCharacters) {
var result = new StringBuf();
for (i in 0...argument.length) {
var c = argument.charCodeAt(i);
if (winMetaCharacters.indexOf(c) >= 0) {
result.addChar("^".code);
}
result.addChar(c);
}
return result.toString();
} else {
return argument;
}
}
}

View File

@ -0,0 +1,508 @@
/*
* 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 haxe;
import haxe.ds.List;
using StringTools;
private enum TemplateExpr {
OpVar(v:String);
OpExpr(expr:Void->Dynamic);
OpIf(expr:Void->Dynamic, eif:TemplateExpr, eelse:TemplateExpr);
OpStr(str:String);
OpBlock(l:List<TemplateExpr>);
OpForeach(expr:Void->Dynamic, loop:TemplateExpr);
OpMacro(name:String, params:List<TemplateExpr>);
}
private typedef Token = {
var s:Bool;
var p:String;
var l:Array<String>;
}
private typedef ExprToken = {
var s:Bool;
var p:String;
}
/**
`Template` provides a basic templating mechanism to replace values in a source
String, and to have some basic logic.
A complete documentation of the supported syntax is available at:
<https://haxe.org/manual/std-template.html>
**/
class Template {
static var splitter = ~/(::[A-Za-z0-9_ ()&|!+=\/><*."-]+::|\$\$([A-Za-z0-9_-]+)\()/;
static var expr_splitter = ~/(\(|\)|[ \r\n\t]*"[^"]*"[ \r\n\t]*|[!+=\/><*.&|-]+)/;
static var expr_trim = ~/^[ ]*([^ ]+)[ ]*$/;
static var expr_int = ~/^[0-9]+$/;
static var expr_float = ~/^([+-]?)(?=\d|,\d)\d*(,\d*)?([Ee]([+-]?\d+))?$/;
/**
Global replacements which are used across all `Template` instances. This
has lower priority than the context argument of `execute()`.
**/
public static var globals:Dynamic = {};
// To avoid issues with DCE, keep the array iterator.
@:ifFeature("haxe.Template.run") static var hxKeepArrayIterator = [].iterator();
var expr:TemplateExpr;
var context:Dynamic;
var macros:Dynamic;
var stack:List<Dynamic>;
var buf:StringBuf;
/**
Creates a new `Template` instance from `str`.
`str` is parsed into tokens, which are stored for internal use. This
means that multiple `execute()` operations on a single `Template` instance
are more efficient than one `execute()` operations on multiple `Template`
instances.
If `str` is `null`, the result is unspecified.
**/
public function new(str:String) {
var tokens = parseTokens(str);
expr = parseBlock(tokens);
if (!tokens.isEmpty())
throw "Unexpected '" + tokens.first().s + "'";
}
/**
Executes `this` `Template`, taking into account `context` for
replacements and `macros` for callback functions.
If `context` has a field `name`, its value replaces all occurrences of
`::name::` in the `Template`. Otherwise `Template.globals` is checked instead,
If `name` is not a field of that either, `::name::` is replaced with `null`.
If `macros` has a field `name`, all occurrences of `$$name(args)` are
replaced with the result of calling that field. The first argument is
always the `resolve()` method, followed by the given arguments.
If `macros` has no such field, the result is unspecified.
If `context` is `null`, the result is unspecified. If `macros` is `null`,
no macros are used.
**/
public function execute(context:Dynamic, ?macros:Dynamic):String {
this.macros = if (macros == null) {} else macros;
this.context = context;
stack = new List();
buf = new StringBuf();
run(expr);
return buf.toString();
}
function resolve(v:String):Dynamic {
if (v == "__current__")
return context;
if (Reflect.isObject(context)) {
var value = Reflect.getProperty(context, v);
if (value != null || Reflect.hasField(context, v))
return value;
}
for (ctx in stack) {
var value = Reflect.getProperty(ctx, v);
if (value != null || Reflect.hasField(ctx, v))
return value;
}
return Reflect.field(globals, v);
}
function parseTokens(data:String) {
var tokens = new List<Token>();
while (splitter.match(data)) {
var p = splitter.matchedPos();
if (p.pos > 0)
tokens.add({p: data.substr(0, p.pos), s: true, l: null});
// : ?
if (data.charCodeAt(p.pos) == 58) {
tokens.add({p: data.substr(p.pos + 2, p.len - 4), s: false, l: null});
data = splitter.matchedRight();
continue;
}
// macro parse
var parp = p.pos + p.len;
var npar = 1;
var params = [];
var part = "";
while (true) {
var c = data.charCodeAt(parp);
parp++;
if (c == 40) {
npar++;
} else if (c == 41) {
npar--;
if (npar <= 0)
break;
} else if (c == null) {
throw "Unclosed macro parenthesis";
}
if (c == 44 && npar == 1) {
params.push(part);
part = "";
} else {
part += String.fromCharCode(c);
}
}
params.push(part);
tokens.add({p: splitter.matched(2), s: false, l: params});
data = data.substr(parp, data.length - parp);
}
if (data.length > 0)
tokens.add({p: data, s: true, l: null});
return tokens;
}
function parseBlock(tokens:List<Token>) {
var l = new List();
while (true) {
var t = tokens.first();
if (t == null)
break;
if (!t.s && (t.p == "end" || t.p == "else" || t.p.substr(0, 7) == "elseif "))
break;
l.add(parse(tokens));
}
if (l.length == 1)
return l.first();
return OpBlock(l);
}
function parse(tokens:List<Token>) {
var t = tokens.pop();
var p = t.p;
if (t.s)
return OpStr(p);
// macro
if (t.l != null) {
var pe = new List();
for (p in t.l)
pe.add(parseBlock(parseTokens(p)));
return OpMacro(p, pe);
}
function kwdEnd(kwd:String):Int {
var pos = -1;
var length = kwd.length;
if (p.substr(0, length) == kwd) {
pos = length;
for (c in p.substr(length)) {
switch c {
case ' '.code: pos++;
case _: break;
}
}
}
return pos;
}
// 'end' , 'else', 'elseif' can't be found here
var pos = kwdEnd("if");
if (pos > 0) {
p = p.substr(pos, p.length - pos);
var e = parseExpr(p);
var eif = parseBlock(tokens);
var t = tokens.first();
var eelse;
if (t == null)
throw "Unclosed 'if'";
if (t.p == "end") {
tokens.pop();
eelse = null;
} else if (t.p == "else") {
tokens.pop();
eelse = parseBlock(tokens);
t = tokens.pop();
if (t == null || t.p != "end")
throw "Unclosed 'else'";
} else { // elseif
t.p = t.p.substr(4, t.p.length - 4);
eelse = parse(tokens);
}
return OpIf(e, eif, eelse);
}
var pos = kwdEnd("foreach");
if (pos >= 0) {
p = p.substr(pos, p.length - pos);
var e = parseExpr(p);
var efor = parseBlock(tokens);
var t = tokens.pop();
if (t == null || t.p != "end")
throw "Unclosed 'foreach'";
return OpForeach(e, efor);
}
if (expr_splitter.match(p))
return OpExpr(parseExpr(p));
return OpVar(p);
}
function parseExpr(data:String) {
var l = new List<ExprToken>();
var expr = data;
while (expr_splitter.match(data)) {
var p = expr_splitter.matchedPos();
var k = p.pos + p.len;
if (p.pos != 0)
l.add({p: data.substr(0, p.pos), s: true});
var p = expr_splitter.matched(0);
l.add({p: p, s: p.indexOf('"') >= 0});
data = expr_splitter.matchedRight();
}
if (data.length != 0) {
for (i => c in data) {
switch c {
case ' '.code:
case _:
l.add({p: data.substr(i), s: true});
break;
}
}
}
var e:Void->Dynamic;
try {
e = makeExpr(l);
if (!l.isEmpty())
throw l.first().p;
} catch (s:String) {
throw "Unexpected '" + s + "' in " + expr;
}
return function() {
try {
return e();
} catch (exc:Dynamic) {
throw "Error : " + Std.string(exc) + " in " + expr;
}
}
}
function makeConst(v:String):Void->Dynamic {
expr_trim.match(v);
v = expr_trim.matched(1);
if (v.charCodeAt(0) == 34) {
var str = v.substr(1, v.length - 2);
return function() return str;
}
if (expr_int.match(v)) {
var i = Std.parseInt(v);
return function() {
return i;
};
}
if (expr_float.match(v)) {
var f = Std.parseFloat(v);
return function() {
return f;
};
}
var me = this;
return function() {
return me.resolve(v);
};
}
function makePath(e:Void->Dynamic, l:List<ExprToken>) {
var p = l.first();
if (p == null || p.p != ".")
return e;
l.pop();
var field = l.pop();
if (field == null || !field.s)
throw field.p;
var f = field.p;
expr_trim.match(f);
f = expr_trim.matched(1);
return makePath(function() {
return Reflect.field(e(), f);
}, l);
}
function makeExpr(l) {
return makePath(makeExpr2(l), l);
}
function skipSpaces(l:List<ExprToken>) {
var p = l.first();
while (p != null) {
for (c in p.p) {
if (c != " ".code) {
return;
}
}
l.pop();
p = l.first();
}
}
function makeExpr2(l:List<ExprToken>):Void->Dynamic {
skipSpaces(l);
var p = l.pop();
skipSpaces(l);
if (p == null)
throw "<eof>";
if (p.s)
return makeConst(p.p);
switch (p.p) {
case "(":
skipSpaces(l);
var e1:Dynamic = makeExpr(l);
skipSpaces(l);
var p = l.pop();
if (p == null || p.s)
throw p;
if (p.p == ")")
return e1;
skipSpaces(l);
var e2:Dynamic = makeExpr(l);
skipSpaces(l);
var p2 = l.pop();
skipSpaces(l);
if (p2 == null || p2.p != ")")
throw p2;
return switch (p.p) {
case "+": function() {
return cast e1() + e2();
};
case "-": function() {
return cast e1() - e2();
};
case "*": function() {
return cast e1() * e2();
};
case "/": function() {
return cast e1() / e2();
};
case ">": function() {
return cast e1() > e2();
};
case "<": function() {
return cast e1() < e2();
};
case ">=": function() {
return cast e1() >= e2();
};
case "<=": function() {
return cast e1() <= e2();
};
case "==": function() {
return cast e1() == e2();
};
case "!=": function() {
return cast e1() != e2();
};
case "&&": function() {
return cast e1() && e2();
};
case "||": function() {
return cast e1() || e2();
};
default: throw "Unknown operation " + p.p;
}
case "!":
var e:Void->Dynamic = makeExpr(l);
return function() {
var v:Dynamic = e();
return (v == null || v == false);
};
case "-":
var e = makeExpr(l);
return function() {
return -e();
};
}
throw p.p;
}
function run(e:TemplateExpr) {
switch (e) {
case OpVar(v):
buf.add(Std.string(resolve(v)));
case OpExpr(e):
buf.add(Std.string(e()));
case OpIf(e, eif, eelse):
var v:Dynamic = e();
if (v == null || v == false) {
if (eelse != null)
run(eelse);
} else
run(eif);
case OpStr(str):
buf.add(str);
case OpBlock(l):
for (e in l)
run(e);
case OpForeach(e, loop):
var v:Dynamic = e();
try {
var x:Dynamic = v.iterator();
if (x.hasNext == null)
throw null;
v = x;
} catch (e:Dynamic)
try {
if (v.hasNext == null)
throw null;
} catch (e:Dynamic) {
throw "Cannot iter on " + v;
}
stack.push(context);
var v:Iterator<Dynamic> = v;
for (ctx in v) {
context = ctx;
run(loop);
}
context = stack.pop();
case OpMacro(m, params):
var v:Dynamic = Reflect.field(macros, m);
var pl = new Array<Dynamic>();
var old = buf;
pl.push(resolve);
for (p in params) {
switch (p) {
case OpVar(v): pl.push(resolve(v));
default:
buf = new StringBuf();
run(p);
pl.push(buf.toString());
}
}
buf = old;
try {
buf.add(Std.string(Reflect.callMethod(macros, v, pl)));
} catch (e:Dynamic) {
var plstr = try pl.join(",") catch (e:Dynamic) "???";
var msg = "Macro call " + m + "(" + plstr + ") failed (" + Std.string(e) + ")";
#if neko
neko.Lib.rethrow(msg);
#else
throw msg;
#end
}
}
}
}

View File

@ -0,0 +1,193 @@
/*
* 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 haxe;
#if (target.threaded && !cppia)
import sys.thread.Thread;
import sys.thread.EventLoop;
#end
/**
The `Timer` class allows you to create asynchronous timers on platforms that
support events.
The intended usage is to create an instance of the `Timer` class with a given
interval, set its `run()` method to a custom function to be invoked and
eventually call `stop()` to stop the `Timer`.
Note that a running `Timer` may or may not prevent the program to exit
automatically when `main()` returns.
It is also possible to extend this class and override its `run()` method in
the child class.
**/
class Timer {
#if (flash || js)
private var id:Null<Int>;
#elseif (target.threaded && !cppia)
var thread:Thread;
var eventHandler:EventHandler;
#else
private var event:MainLoop.MainEvent;
#end
/**
Creates a new timer that will run every `time_ms` milliseconds.
After creating the Timer instance, it calls `this.run` repeatedly,
with delays of `time_ms` milliseconds, until `this.stop` is called.
The first invocation occurs after `time_ms` milliseconds, not
immediately.
The accuracy of this may be platform-dependent.
**/
public function new(time_ms:Int) {
#if flash
var me = this;
id = untyped __global__["flash.utils.setInterval"](function() {
me.run();
}, time_ms);
#elseif js
var me = this;
id = untyped setInterval(function() me.run(), time_ms);
#elseif (target.threaded && !cppia)
thread = Thread.current();
eventHandler = thread.events.repeat(() -> this.run(), time_ms);
#else
var dt = time_ms / 1000;
event = MainLoop.add(function() {
@:privateAccess event.nextRun += dt;
run();
});
event.delay(dt);
#end
}
/**
Stops `this` Timer.
After calling this method, no additional invocations of `this.run`
will occur.
It is not possible to restart `this` Timer once stopped.
**/
public function stop() {
#if (flash || js)
if (id == null)
return;
#if flash
untyped __global__["flash.utils.clearInterval"](id);
#elseif js
untyped clearInterval(id);
#end
id = null;
#elseif (target.threaded && !cppia)
thread.events.cancel(eventHandler);
#else
if (event != null) {
event.stop();
event = null;
}
#end
}
/**
This method is invoked repeatedly on `this` Timer.
It can be overridden in a subclass, or rebound directly to a custom
function:
```haxe
var timer = new haxe.Timer(1000); // 1000ms delay
timer.run = function() { ... }
```
Once bound, it can still be rebound to different functions until `this`
Timer is stopped through a call to `this.stop`.
**/
public dynamic function run() {}
/**
Invokes `f` after `time_ms` milliseconds.
This is a convenience function for creating a new Timer instance with
`time_ms` as argument, binding its `run()` method to `f` and then stopping
`this` Timer upon the first invocation.
If `f` is `null`, the result is unspecified.
**/
public static function delay(f:Void->Void, time_ms:Int) {
var t = new haxe.Timer(time_ms);
t.run = function() {
t.stop();
f();
};
return t;
}
/**
Measures the time it takes to execute `f`, in seconds with fractions.
This is a convenience function for calculating the difference between
`Timer.stamp()` before and after the invocation of `f`.
The difference is passed as argument to `Log.trace()`, with `"s"` appended
to denote the unit. The optional `pos` argument is passed through.
If `f` is `null`, the result is unspecified.
**/
public static function measure<T>(f:Void->T, ?pos:PosInfos):T {
var t0 = stamp();
var r = f();
Log.trace((stamp() - t0) + "s", pos);
return r;
}
/**
Returns a timestamp, in seconds with fractions.
The value itself might differ depending on platforms, only differences
between two values make sense.
**/
public static inline function stamp():Float {
#if flash
return flash.Lib.getTimer() / 1000;
#elseif js
#if nodejs
var hrtime = js.Syntax.code('process.hrtime()'); // [seconds, remaining nanoseconds]
return hrtime[0] + hrtime[1] / 1e9;
#else
return @:privateAccess HxOverrides.now() / 1000;
#end
#elseif cpp
return untyped __global__.__time_stamp();
#elseif python
return Sys.cpuTime();
#elseif sys
return Sys.time();
#else
return 0;
#end
}
}

View File

@ -0,0 +1,191 @@
/*
* 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 haxe;
/**
Cross platform UCS2 string API.
**/
abstract Ucs2(String) {
extern public var length(get, never):Int;
extern inline function new(str:String):Void {
// this implementation only allows platforms which have native UCS2 String.
// other platforms should create a shadow class in their _std directory
#if !(flash || js)
throw "Ucs2 String not supported on this platform";
#end
this = str;
}
extern inline function get_length() {
return this.length;
}
/**
Returns a Ucs2 where all characters of `this` Ucs2 are upper case.
Affects the characters `a-z`. Other characters remain unchanged.
**/
extern public inline function toUpperCase():Ucs2 {
return new Ucs2(this.toUpperCase());
}
/**
Returns a Ucs2 where all characters of `this` Ucs2 are lower case.
Affects the characters `A-Z`. Other characters remain unchanged.
**/
extern public inline function toLowerCase():Ucs2 {
return new Ucs2(this.toLowerCase());
}
/**
Returns the character at position `index` of `this` Ucs2.
If `index` is negative or exceeds `this.length`, the empty Ucs2 ""
is returned.
**/
extern public inline function charAt(index:Int):Ucs2 {
return new Ucs2(this.charAt(index));
}
/**
Returns the character code at position `index` of `this` Ucs2.
If `index` is negative or exceeds `this.length`, `null` is returned.
To obtain the character code of a single character, `"x".code` can be used
instead to extern public inline the character code at compile time. Note that this
only works on Ucs2 literals of length 1.
**/
extern public inline function charCodeAt(index:Int):Null<Int> {
return this.charCodeAt(index);
}
/**
Returns the position of the leftmost occurrence of `str` within `this`
Ucs2.
If `startIndex` is given, the search is performed within the substring
of `this` Ucs2 starting from `startIndex`. Otherwise the search is
performed within `this` Ucs2. In either case, the returned position
is relative to the beginning of `this` Ucs2.
If `str` cannot be found, -1 is returned.
**/
extern public inline function indexOf(str:Ucs2, ?startIndex:Int):Int {
return this.indexOf(str.toNativeString(), startIndex);
}
/**
Returns the position of the rightmost occurrence of `str` within `this`
Ucs2.
If `startIndex` is given, the search is performed within the substring
of `this` Ucs2 from 0 to `startIndex`. Otherwise the search is
performed within `this` Ucs2. In either case, the returned position
is relative to the beginning of `this` Ucs2.
If `str` cannot be found, -1 is returned.
**/
extern public inline function lastIndexOf(str:Ucs2, ?startIndex:Int):Int {
return this.lastIndexOf(str.toNativeString(), startIndex);
}
/**
Splits `this` Ucs2 at each occurrence of `delimiter`.
If `this` Ucs2 is the empty Ucs2 "", the result is not consistent
across targets and may either be `[]` (on Js, Cpp) or `[""]`.
If `delimiter` is the empty Ucs2 "", `this` Ucs2 is split into an
Array of `this.length` elements, where the elements correspond to the
characters of `this` Ucs2.
If `delimiter` is not found within `this` Ucs2, the result is an Array
with one element, which equals `this` Ucs2.
If `delimiter` is null, the result is unspecified.
Otherwise, `this` Ucs2 is split into parts at each occurrence of
`delimiter`. If `this` Ucs2 starts (or ends) with `delimiter`, the
result Array contains a leading (or trailing) empty Ucs2 "" element.
Two subsequent delimiters also result in an empty Ucs2 "" element.
**/
extern public inline function split(delimiter:Ucs2):Array<Ucs2> {
return cast this.split(delimiter.toNativeString());
}
/**
Returns `len` characters of `this` Ucs2, starting at position `pos`.
If `len` is omitted, all characters from position `pos` to the end of
`this` Ucs2 are included.
If `pos` is negative, its value is calculated from the end of `this`
Ucs2 by `this.length + pos`. If this yields a negative value, 0 is
used instead.
If the calculated position + `len` exceeds `this.length`, the characters
from that position to the end of `this` Ucs2 are returned.
If `len` is negative, the result is unspecified.
**/
extern public inline function substr(pos:Int, ?len:Int):Ucs2 {
return new Ucs2(this.substr(pos, len));
}
/**
Returns the part of `this` Ucs2 from `startIndex` to `endIndex`.
If `startIndex` or `endIndex` are negative, 0 is used instead.
If `startIndex` exceeds `endIndex`, they are swapped.
If the (possibly swapped) `endIndex` is omitted or exceeds
`this.length`, `this.length` is used instead.
If the (possibly swapped) `startIndex` exceeds `this.length`, the empty
Ucs2 "" is returned.
**/
extern public inline function substring(startIndex:Int, ?endIndex:Int):Ucs2 {
return new Ucs2(this.substring(startIndex, endIndex));
}
/**
Returns the native underlying String.
**/
extern public inline function toNativeString():String {
return this;
}
/**
Returns the Ucs2 corresponding to the character code `code`.
If `code` is negative or has another invalid value, the result is
unspecified.
**/
extern public static inline function fromCharCode(code:Int):Ucs2 {
return new Ucs2(String.fromCharCode(code));
}
}

View File

@ -0,0 +1,537 @@
/*
* 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 haxe;
using haxe.Unserializer;
import haxe.ds.List;
@:noDoc
typedef TypeResolver = {
function resolveClass(name:String):Class<Dynamic>;
function resolveEnum(name:String):Enum<Dynamic>;
}
/**
The `Unserializer` class is the complement to the `Serializer` class. It parses
a serialization `String` and creates objects from the contained data.
This class can be used in two ways:
- create a `new Unserializer()` instance with a given serialization
String, then call its `unserialize()` method until all values are
extracted
- call `Unserializer.run()` to unserialize a single value from a given
String
The specification of the serialization format can be found here:
<https://haxe.org/manual/serialization/format>
**/
class Unserializer {
/**
This value can be set to use custom type resolvers.
A type resolver finds a `Class` or `Enum` instance from a given `String`.
By default, the Haxe `Type` Api is used.
A type resolver must provide two methods:
1. `resolveClass(name:String):Class<Dynamic>` is called to determine a
`Class` from a class name
2. `resolveEnum(name:String):Enum<Dynamic>` is called to determine an
`Enum` from an enum name
This value is applied when a new `Unserializer` instance is created.
Changing it afterwards has no effect on previously created instances.
**/
public static var DEFAULT_RESOLVER:TypeResolver = new DefaultResolver();
static var BASE64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789%:";
#if !neko
static var CODES = null;
static function initCodes() {
var codes = #if flash new flash.utils.ByteArray(); #else new Array(); #end
for (i in 0...BASE64.length)
codes[StringTools.fastCodeAt(BASE64, i)] = i;
return codes;
}
#end
var buf:String;
var pos:Int;
var length:Int;
var cache:Array<Dynamic>;
var scache:Array<String>;
var resolver:TypeResolver;
#if neko
var upos:Int;
#end
/**
Creates a new Unserializer instance, with its internal buffer
initialized to `buf`.
This does not parse `buf` immediately. It is parsed only when calls to
`this.unserialize` are made.
Each Unserializer instance maintains its own cache.
**/
public function new(buf:String) {
this.buf = buf;
length = this.buf.fastLength();
pos = 0;
#if neko
upos = 0;
#end
scache = new Array();
cache = new Array();
var r = DEFAULT_RESOLVER;
if (r == null) {
r = new DefaultResolver();
DEFAULT_RESOLVER = r;
}
resolver = r;
}
/**
Sets the type resolver of `this` Unserializer instance to `r`.
If `r` is `null`, a special resolver is used which returns `null` for all
input values.
See `DEFAULT_RESOLVER` for more information on type resolvers.
**/
public function setResolver(r) {
if (r == null)
resolver = NullResolver.instance;
else
resolver = r;
}
/**
Gets the type resolver of `this` Unserializer instance.
See `DEFAULT_RESOLVER` for more information on type resolvers.
**/
public function getResolver() {
return resolver;
}
inline function get(p:Int):Int {
#if php
return p >= length ? 0 : buf.fastCharCodeAt(p);
#else
return StringTools.fastCodeAt(buf, p);
#end
}
function readDigits() {
var k = 0;
var s = false;
var fpos = pos;
while (true) {
var c = get(pos);
if (StringTools.isEof(c))
break;
if (c == "-".code) {
if (pos != fpos)
break;
s = true;
pos++;
continue;
}
if (c < "0".code || c > "9".code)
break;
k = k * 10 + (c - "0".code);
pos++;
}
if (s)
k *= -1;
return k;
}
function readFloat() {
var p1 = pos;
while (true) {
var c = get(pos);
if (StringTools.isEof(c))
break;
// + - . , 0-9
if ((c >= 43 && c < 58) || c == "e".code || c == "E".code)
pos++;
else
break;
}
return Std.parseFloat(buf.fastSubstr(p1, pos - p1));
}
function unserializeObject(o:{}) {
while (true) {
if (pos >= length)
throw "Invalid object";
if (get(pos) == "g".code)
break;
var k:Dynamic = unserialize();
if (!Std.isOfType(k, String))
throw "Invalid object key";
var v = unserialize();
Reflect.setField(o, k, v);
}
pos++;
}
function unserializeEnum<T>(edecl:Enum<T>, tag:String) {
if (get(pos++) != ":".code)
throw "Invalid enum format";
var nargs = readDigits();
if (nargs == 0)
return Type.createEnum(edecl, tag);
var args = new Array();
while (nargs-- > 0)
args.push(unserialize());
return Type.createEnum(edecl, tag, args);
}
/**
Unserializes the next part of `this` Unserializer instance and returns
the according value.
This function may call `this.resolver.resolveClass` to determine a
Class from a String, and `this.resolver.resolveEnum` to determine an
Enum from a String.
If `this` Unserializer instance contains no more or invalid data, an
exception is thrown.
This operation may fail on structurally valid data if a type cannot be
resolved or if a field cannot be set. This can happen when unserializing
Strings that were serialized on a different Haxe target, in which the
serialization side has to make sure not to include platform-specific
data.
Classes are created from `Type.createEmptyInstance`, which means their
constructors are not called.
**/
public function unserialize():Dynamic {
switch (get(pos++)) {
case "n".code:
return null;
case "t".code:
return true;
case "f".code:
return false;
case "z".code:
return 0;
case "i".code:
return readDigits();
case "d".code:
return readFloat();
case "y".code:
var len = readDigits();
if (get(pos++) != ":".code || length - pos < len)
throw "Invalid string length";
var s = buf.fastSubstr(pos, len);
pos += len;
s = StringTools.urlDecode(s);
scache.push(s);
return s;
case "k".code:
return Math.NaN;
case "m".code:
return Math.NEGATIVE_INFINITY;
case "p".code:
return Math.POSITIVE_INFINITY;
case "a".code:
var buf = buf;
var a = new Array<Dynamic>();
#if cpp
var cachePos = cache.length;
#end
cache.push(a);
while (true) {
var c = get(pos);
if (c == "h".code) {
pos++;
break;
}
if (c == "u".code) {
pos++;
var n = readDigits();
a[a.length + n - 1] = null;
} else
a.push(unserialize());
}
#if cpp
return cache[cachePos] = cpp.NativeArray.resolveVirtualArray(a);
#else
return a;
#end
case "o".code:
var o = {};
cache.push(o);
unserializeObject(o);
return o;
case "r".code:
var n = readDigits();
if (n < 0 || n >= cache.length)
throw "Invalid reference";
return cache[n];
case "R".code:
var n = readDigits();
if (n < 0 || n >= scache.length)
throw "Invalid string reference";
return scache[n];
case "x".code:
throw unserialize();
case "c".code:
var name = unserialize();
var cl = resolver.resolveClass(name);
if (cl == null)
throw "Class not found " + name;
var o = Type.createEmptyInstance(cl);
cache.push(o);
unserializeObject(o);
return o;
case "w".code:
var name = unserialize();
var edecl = resolver.resolveEnum(name);
if (edecl == null)
throw "Enum not found " + name;
var e = unserializeEnum(edecl, unserialize());
cache.push(e);
return e;
case "j".code:
var name = unserialize();
var edecl = resolver.resolveEnum(name);
if (edecl == null)
throw "Enum not found " + name;
pos++; /* skip ':' */
var index = readDigits();
var tag = Type.getEnumConstructs(edecl)[index];
if (tag == null)
throw "Unknown enum index " + name + "@" + index;
var e = unserializeEnum(edecl, tag);
cache.push(e);
return e;
case "l".code:
var l = new List();
cache.push(l);
var buf = buf;
while (get(pos) != "h".code)
l.add(unserialize());
pos++;
return l;
case "b".code:
var h = new haxe.ds.StringMap();
cache.push(h);
var buf = buf;
while (get(pos) != "h".code) {
var s = unserialize();
h.set(s, unserialize());
}
pos++;
return h;
case "q".code:
var h = new haxe.ds.IntMap();
cache.push(h);
var buf = buf;
var c = get(pos++);
while (c == ":".code) {
var i = readDigits();
h.set(i, unserialize());
c = get(pos++);
}
if (c != "h".code)
throw "Invalid IntMap format";
return h;
case "M".code:
var h = new haxe.ds.ObjectMap();
cache.push(h);
var buf = buf;
while (get(pos) != "h".code) {
var s = unserialize();
h.set(s, unserialize());
}
pos++;
return h;
case "v".code:
var d;
if (get(pos) >= '0'.code && get(pos) <= '9'.code && get(pos + 1) >= '0'.code && get(pos + 1) <= '9'.code && get(pos + 2) >= '0'.code
&& get(pos + 2) <= '9'.code && get(pos + 3) >= '0'.code && get(pos + 3) <= '9'.code && get(pos + 4) == '-'.code) {
// Included for backwards compatibility
d = Date.fromString(buf.fastSubstr(pos, 19));
pos += 19;
} else
d = Date.fromTime(readFloat());
cache.push(d);
return d;
case "s".code:
var len = readDigits();
var buf = buf;
if (get(pos++) != ":".code || length - pos < len)
throw "Invalid bytes length";
#if neko
var bytes = haxe.io.Bytes.ofData(base_decode(untyped buf.fastSubstr(pos, len).__s, untyped BASE64.__s));
#elseif php
var phpEncoded = php.Global.strtr(buf.fastSubstr(pos, len), '%:', '+/');
var bytes = haxe.io.Bytes.ofData(php.Global.base64_decode(phpEncoded));
#else
var codes = CODES;
if (codes == null) {
codes = initCodes();
CODES = codes;
}
var i = pos;
var rest = len & 3;
var size = (len >> 2) * 3 + ((rest >= 2) ? rest - 1 : 0);
var max = i + (len - rest);
var bytes = haxe.io.Bytes.alloc(size);
var bpos = 0;
while (i < max) {
var c1 = codes[StringTools.fastCodeAt(buf, i++)];
var c2 = codes[StringTools.fastCodeAt(buf, i++)];
bytes.set(bpos++, (c1 << 2) | (c2 >> 4));
var c3 = codes[StringTools.fastCodeAt(buf, i++)];
bytes.set(bpos++, (c2 << 4) | (c3 >> 2));
var c4 = codes[StringTools.fastCodeAt(buf, i++)];
bytes.set(bpos++, (c3 << 6) | c4);
}
if (rest >= 2) {
var c1 = codes[StringTools.fastCodeAt(buf, i++)];
var c2 = codes[StringTools.fastCodeAt(buf, i++)];
bytes.set(bpos++, (c1 << 2) | (c2 >> 4));
if (rest == 3) {
var c3 = codes[StringTools.fastCodeAt(buf, i++)];
bytes.set(bpos++, (c2 << 4) | (c3 >> 2));
}
}
#end
pos += len;
cache.push(bytes);
return bytes;
case "C".code:
var name = unserialize();
var cl = resolver.resolveClass(name);
if (cl == null)
throw "Class not found " + name;
var o:Dynamic = Type.createEmptyInstance(cl);
cache.push(o);
o.hxUnserialize(this);
if (get(pos++) != "g".code)
throw "Invalid custom data";
return o;
case "A".code:
var name = unserialize();
var cl = resolver.resolveClass(name);
if (cl == null)
throw "Class not found " + name;
return cl;
case "B".code:
var name = unserialize();
var e = resolver.resolveEnum(name);
if (e == null)
throw "Enum not found " + name;
return e;
default:
}
pos--;
throw("Invalid char " + buf.fastCharAt(pos) + " at position " + pos);
}
/**
Unserializes `v` and returns the according value.
This is a convenience function for creating a new instance of
Unserializer with `v` as buffer and calling its `unserialize()` method
once.
**/
public static function run(v:String):Dynamic {
return new Unserializer(v).unserialize();
}
#if neko
static var base_decode = neko.Lib.load("std", "base_decode", 2);
#end
static inline function fastLength(s:String):Int {
#if php
return php.Global.strlen(s);
#else
return s.length;
#end
}
static inline function fastCharCodeAt(s:String, pos:Int):Int {
#if php
return php.Global.ord((s:php.NativeString)[pos]);
#else
return s.charCodeAt(pos);
#end
}
static inline function fastCharAt(s:String, pos:Int):String {
#if php
return (s:php.NativeString)[pos];
#else
return s.charAt(pos);
#end
}
static inline function fastSubstr(s:String, pos:Int, length:Int):String {
#if php
return php.Global.substr(s, pos, length);
#else
return s.substr(pos, length);
#end
}
}
private class DefaultResolver {
public function new() {}
public inline function resolveClass(name:String):Class<Dynamic>
return Type.resolveClass(name);
public inline function resolveEnum(name:String):Enum<Dynamic>
return Type.resolveEnum(name);
}
private class NullResolver {
function new() {}
public inline function resolveClass(name:String):Class<Dynamic>
return null;
public inline function resolveEnum(name:String):Enum<Dynamic>
return null;
public static var instance(get, null):NullResolver;
inline static function get_instance():NullResolver {
if (instance == null)
instance = new NullResolver();
return instance;
}
}

View File

@ -0,0 +1,114 @@
/*
* 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 haxe;
/**
Since not all platforms guarantee that `String` always uses UTF-8 encoding, you
can use this cross-platform API to perform operations on such strings.
**/
@:deprecated('haxe.Utf8 is deprecated. Use UnicodeString instead.')
class Utf8 {
var __b:String;
/**
Allocate a new Utf8 buffer using an optional bytes size.
**/
public function new(?size:Int) {
__b = "";
}
/**
Add the given UTF8 character code to the buffer.
**/
public inline function addChar(c:Int):Void {
__b += String.fromCharCode(c);
}
/**
Returns the buffer converted to a String.
**/
public inline function toString():String {
return __b;
}
/**
Call the `chars` function for each UTF8 char of the string.
**/
public static function iter(s:String, chars:Int->Void) {
for (i in 0...s.length)
chars(s.charCodeAt(i));
}
/**
Encode the input ISO string into the corresponding UTF8 one.
**/
public static function encode(s:String):String {
throw new haxe.exceptions.NotImplementedException();
}
/**
Decode an UTF8 string back to an ISO string.
Throw an exception if a given UTF8 character is not supported by the decoder.
**/
public static function decode(s:String):String {
throw new haxe.exceptions.NotImplementedException();
}
/**
Similar to `String.charCodeAt` but uses the UTF8 character position.
**/
public static inline function charCodeAt(s:String, index:Int):Int {
return s.charCodeAt(index);
}
/**
Tells if the String is correctly encoded as UTF8.
**/
public static inline function validate(s:String):Bool {
return true;
}
/**
Returns the number of UTF8 chars of the String.
**/
#if js
extern
#end
public static inline function length(s:String):Int {
return s.length;
}
/**
Compare two UTF8 strings, character by character.
**/
public static function compare(a:String, b:String):Int {
return a > b ? 1 : (a == b ? 0 : -1);
}
/**
This is similar to `String.substr` but the `pos` and `len` parts are considering UTF8 characters.
**/
public static inline function sub(s:String, pos:Int, len:Int):String {
return s.substr(pos, len);
}
}

View File

@ -0,0 +1,38 @@
package haxe;
/**
An exception containing arbitrary value.
This class is automatically used for throwing values, which don't extend `haxe.Exception`
or native exception type.
For example:
```haxe
throw "Terrible error";
```
will be compiled to
```haxe
throw new ValueException("Terrible error");
```
**/
class ValueException extends Exception {
/**
Thrown value.
**/
public var value(default,null):Any;
public function new(value:Any, ?previous:Exception, ?native:Any):Void {
super(#if js js.Syntax.code('String({0})', value) #else Std.string(value) #end, previous, native);
this.value = value;
}
/**
Extract an originally thrown value.
This method must return the same value on subsequent calls.
Used internally for catching non-native exceptions.
Do _not_ override unless you know what you are doing.
**/
override function unwrap():Any {
return value;
}
}

View File

@ -0,0 +1,76 @@
/*
* 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 haxe.crypto;
/**
Calculates the Adler32 of the given Bytes.
*/
class Adler32 {
var a1:Int;
var a2:Int;
public function new() {
a1 = 1;
a2 = 0;
}
public function get() {
return (a2 << 16) | a1;
}
public function update(b:haxe.io.Bytes, pos, len) {
var a1 = a1, a2 = a2;
for (p in pos...pos + len) {
var c = b.get(p);
a1 = (a1 + c) % 65521;
a2 = (a2 + a1) % 65521;
}
this.a1 = a1;
this.a2 = a2;
}
public function equals(a:Adler32) {
return a.a1 == a1 && a.a2 == a2;
}
public function toString() {
return StringTools.hex(a2, 8) + StringTools.hex(a1, 8);
}
public static function read(i:haxe.io.Input) {
var a = new Adler32();
var a2a = i.readByte();
var a2b = i.readByte();
var a1a = i.readByte();
var a1b = i.readByte();
a.a1 = (a1a << 8) | a1b;
a.a2 = (a2a << 8) | a2b;
return a;
}
public static function make(b:haxe.io.Bytes) {
var a = new Adler32();
a.update(b, 0, b.length);
return a.get();
}
}

View File

@ -0,0 +1,74 @@
/*
* 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 haxe.crypto;
/**
Allows one to encode/decode String and bytes using Base64 encoding.
**/
class Base64 {
public static var CHARS(default, null) = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
public static var BYTES(default, null) = haxe.io.Bytes.ofString(CHARS);
public static var URL_CHARS(default, null) = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
public static var URL_BYTES(default, null) = haxe.io.Bytes.ofString(URL_CHARS);
public static function encode(bytes:haxe.io.Bytes, complement = true):String {
var str = new BaseCode(BYTES).encodeBytes(bytes).toString();
if (complement)
switch (bytes.length % 3) {
case 1:
str += "==";
case 2:
str += "=";
default:
}
return str;
}
public static function decode(str:String, complement = true):haxe.io.Bytes {
if (complement)
while (str.charCodeAt(str.length - 1) == "=".code)
str = str.substr(0, -1);
return new BaseCode(BYTES).decodeBytes(haxe.io.Bytes.ofString(str));
}
public static function urlEncode(bytes:haxe.io.Bytes, complement = false):String {
var str = new BaseCode(URL_BYTES).encodeBytes(bytes).toString();
if (complement)
switch (bytes.length % 3) {
case 1:
str += "==";
case 2:
str += "=";
default:
}
return str;
}
public static function urlDecode(str:String, complement = false):haxe.io.Bytes {
if (complement)
while (str.charCodeAt(str.length - 1) == "=".code)
str = str.substr(0, -1);
return new BaseCode(URL_BYTES).decodeBytes(haxe.io.Bytes.ofString(str));
}
}

View File

@ -0,0 +1,142 @@
/*
* 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 haxe.crypto;
/**
Allows one to encode/decode String and bytes using a power of two base dictionary.
**/
class BaseCode {
var base:haxe.io.Bytes;
var nbits:Int;
var tbl:Array<Int>;
public function new(base:haxe.io.Bytes) {
var len = base.length;
var nbits = 1;
while (len > 1 << nbits)
nbits++;
if (nbits > 8 || len != 1 << nbits)
throw "BaseCode : base length must be a power of two.";
this.base = base;
this.nbits = nbits;
}
public function encodeBytes(b:haxe.io.Bytes):haxe.io.Bytes {
#if (neko && !interp)
return haxe.io.Bytes.ofData(base_encode(b.getData(), base.getData()));
#else
var nbits = this.nbits;
var base = this.base;
var size = Std.int(b.length * 8 / nbits);
var out = haxe.io.Bytes.alloc(size + (((b.length * 8) % nbits == 0) ? 0 : 1));
var buf = 0;
var curbits = 0;
var mask = (1 << nbits) - 1;
var pin = 0;
var pout = 0;
while (pout < size) {
while (curbits < nbits) {
curbits += 8;
buf <<= 8;
buf |= b.get(pin++);
}
curbits -= nbits;
out.set(pout++, base.get((buf >> curbits) & mask));
}
if (curbits > 0)
out.set(pout++, base.get((buf << (nbits - curbits)) & mask));
return out;
#end
}
function initTable() {
var tbl = new Array();
for (i in 0...256)
tbl[i] = -1;
for (i in 0...base.length)
tbl[base.get(i)] = i;
this.tbl = tbl;
}
public function decodeBytes(b:haxe.io.Bytes):haxe.io.Bytes {
#if (neko && !interp)
return haxe.io.Bytes.ofData(base_decode(b.getData(), base.getData()));
#else
var nbits = this.nbits;
var base = this.base;
if (this.tbl == null)
initTable();
var tbl = this.tbl;
var size = (b.length * nbits) >> 3;
var out = haxe.io.Bytes.alloc(size);
var buf = 0;
var curbits = 0;
var pin = 0;
var pout = 0;
while (pout < size) {
while (curbits < 8) {
curbits += nbits;
buf <<= nbits;
var i = tbl[b.get(pin++)];
if (i == -1)
throw "BaseCode : invalid encoded char";
buf |= i;
}
curbits -= 8;
out.set(pout++, (buf >> curbits) & 0xFF);
}
return out;
#end
}
public function encodeString(s:String) {
#if (neko && !interp)
return neko.NativeString.toString(base_encode(neko.NativeString.ofString(s), base.getData()));
#else
return encodeBytes(haxe.io.Bytes.ofString(s)).toString();
#end
}
public function decodeString(s:String) {
#if (neko && !interp)
return neko.NativeString.toString(base_decode(neko.NativeString.ofString(s), base.getData()));
#else
return decodeBytes(haxe.io.Bytes.ofString(s)).toString();
#end
}
public static function encode(s:String, base:String) {
var b = new BaseCode(haxe.io.Bytes.ofString(base));
return b.encodeString(s);
}
public static function decode(s:String, base:String) {
var b = new BaseCode(haxe.io.Bytes.ofString(base));
return b.decodeString(s);
}
#if neko
private static var base_encode = neko.Lib.load("std", "base_encode", 2);
private static var base_decode = neko.Lib.load("std", "base_decode", 2);
#end
}

View File

@ -0,0 +1,64 @@
/*
* 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 haxe.crypto;
/**
Calculates the Crc32 of the given Bytes.
*/
class Crc32 {
var crc:Int;
public inline function new() {
crc = 0xFFFFFFFF;
}
public inline function byte(b:Int) {
var tmp = (crc ^ b) & 0xFF;
for (j in 0...8)
tmp = (tmp >>> 1) ^ (-(tmp & 1) & 0xEDB88320);
crc = (crc >>> 8) ^ tmp;
}
public inline function update(b:haxe.io.Bytes, pos, len) {
var b = b.getData();
for (i in pos...pos + len) {
var tmp = (crc ^ haxe.io.Bytes.fastGet(b, i)) & 0xFF;
for (j in 0...8)
tmp = (tmp >>> 1) ^ (-(tmp & 1) & 0xEDB88320);
crc = (crc >>> 8) ^ tmp;
}
}
public inline function get() {
return crc ^ 0xFFFFFFFF;
}
/**
Calculates the CRC32 of the given data bytes
**/
public static function make(data:haxe.io.Bytes):Int {
var c = new Crc32();
c.update(data, 0, data.length);
return c.get();
}
}

View File

@ -0,0 +1,90 @@
/*
* 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 haxe.crypto;
/**
Hash methods for Hmac calculation.
**/
enum HashMethod {
MD5;
SHA1;
SHA256;
}
/**
Calculates a Hmac of the given Bytes using a HashMethod.
**/
class Hmac {
var method:HashMethod;
var blockSize:Int;
var length:Int;
public function new(hashMethod:HashMethod) {
method = hashMethod;
blockSize = switch (hashMethod) {
case MD5, SHA1, SHA256: 64;
}
length = switch (hashMethod) {
case MD5: 16;
case SHA1: 20;
case SHA256: 32;
}
}
inline function doHash(b:haxe.io.Bytes):haxe.io.Bytes {
return switch (method) {
case MD5: Md5.make(b);
case SHA1: Sha1.make(b);
case SHA256: Sha256.make(b);
}
}
function nullPad(s:haxe.io.Bytes, chunkLen:Int):haxe.io.Bytes {
var r = chunkLen - (s.length % chunkLen);
if (r == chunkLen && s.length != 0)
return s;
var sb = new haxe.io.BytesBuffer();
sb.add(s);
for (x in 0...r)
sb.addByte(0);
return sb.getBytes();
}
public function make(key:haxe.io.Bytes, msg:haxe.io.Bytes):haxe.io.Bytes {
if (key.length > blockSize) {
key = doHash(key);
}
key = nullPad(key, blockSize);
var Ki = new haxe.io.BytesBuffer();
var Ko = new haxe.io.BytesBuffer();
for (i in 0...key.length) {
Ko.addByte(key.get(i) ^ 0x5c);
Ki.addByte(key.get(i) ^ 0x36);
}
// hash(Ko + hash(Ki + message))
Ki.add(msg);
Ko.add(doHash(Ki.getBytes()));
return doHash(Ko.getBytes());
}
}

View File

@ -0,0 +1,268 @@
/*
* 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 haxe.crypto;
/**
Creates a MD5 of a String.
**/
class Md5 {
public static function encode(s:String):String {
var m = new Md5();
var h = m.doEncode(str2blks(s));
return m.hex(h);
}
public static function make(b:haxe.io.Bytes):haxe.io.Bytes {
var h = new Md5().doEncode(bytes2blks(b));
var out = haxe.io.Bytes.alloc(16);
var p = 0;
for (i in 0...4) {
out.set(p++, h[i] & 0xFF);
out.set(p++, (h[i] >> 8) & 0xFF);
out.set(p++, (h[i] >> 16) & 0xFF);
out.set(p++, h[i] >>> 24);
}
return out;
}
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Copyright (C) Paul Johnston 1999 - 2000.
* Updated by Greg Holt 2000 - 2001.
* See http://pajhome.org.uk/site/legal.html for details.
*/
function new() {}
function bitOR(a, b) {
var lsb = (a & 0x1) | (b & 0x1);
var msb31 = (a >>> 1) | (b >>> 1);
return (msb31 << 1) | lsb;
}
function bitXOR(a, b) {
var lsb = (a & 0x1) ^ (b & 0x1);
var msb31 = (a >>> 1) ^ (b >>> 1);
return (msb31 << 1) | lsb;
}
function bitAND(a, b) {
var lsb = (a & 0x1) & (b & 0x1);
var msb31 = (a >>> 1) & (b >>> 1);
return (msb31 << 1) | lsb;
}
function addme(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
function hex(a:Array<Int>) {
var str = "";
var hex_chr = "0123456789abcdef";
for (num in a)
for (j in 0...4)
str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) + hex_chr.charAt((num >> (j * 8)) & 0x0F);
return str;
}
static function bytes2blks(b:haxe.io.Bytes) {
var nblk = ((b.length + 8) >> 6) + 1;
var blks = new Array();
// preallocate size
var blksSize = nblk * 16;
#if (neko || cs || cpp || java || hl)
blks[blksSize - 1] = 0;
#end
#if !(cpp || cs || hl) // C++ and C# will already initialize them with zeroes.
for (i in 0...blksSize)
blks[i] = 0;
#end
var i = 0;
while (i < b.length) {
blks[i >> 2] |= b.get(i) << ((((b.length << 3) + i) & 3) << 3);
i++;
}
blks[i >> 2] |= 0x80 << (((b.length * 8 + i) % 4) * 8);
var l = b.length * 8;
var k = nblk * 16 - 2;
blks[k] = (l & 0xFF);
blks[k] |= ((l >>> 8) & 0xFF) << 8;
blks[k] |= ((l >>> 16) & 0xFF) << 16;
blks[k] |= ((l >>> 24) & 0xFF) << 24;
return blks;
}
static function str2blks(str:String) {
#if target.unicode
var str = haxe.io.Bytes.ofString(str);
#end
var nblk = ((str.length + 8) >> 6) + 1;
var blks = new Array();
// preallocate size
var blksSize = nblk * 16;
#if (neko || eval || cs || cpp || java || hl)
blks[blksSize - 1] = 0;
#end
#if !(cpp || cs || hl) // C++ and C# will already initialize them with zeroes.
for (i in 0...blksSize)
blks[i] = 0;
#end
var i = 0;
var max = str.length;
var l = max * 8;
while (i < max) {
blks[i >> 2] |= #if target.unicode str.get(i) #else StringTools.fastCodeAt(str, i) #end << (((l + i) % 4) * 8);
i++;
}
blks[i >> 2] |= 0x80 << (((l + i) % 4) * 8);
var k = nblk * 16 - 2;
blks[k] = (l & 0xFF);
blks[k] |= ((l >>> 8) & 0xFF) << 8;
blks[k] |= ((l >>> 16) & 0xFF) << 16;
blks[k] |= ((l >>> 24) & 0xFF) << 24;
return blks;
}
function rol(num, cnt) {
return (num << cnt) | (num >>> (32 - cnt));
}
function cmn(q, a, b, x, s, t) {
return addme(rol((addme(addme(a, q), addme(x, t))), s), b);
}
function ff(a, b, c, d, x, s, t) {
return cmn(bitOR(bitAND(b, c), bitAND((~b), d)), a, b, x, s, t);
}
function gg(a, b, c, d, x, s, t) {
return cmn(bitOR(bitAND(b, d), bitAND(c, (~d))), a, b, x, s, t);
}
function hh(a, b, c, d, x, s, t) {
return cmn(bitXOR(bitXOR(b, c), d), a, b, x, s, t);
}
function ii(a, b, c, d, x, s, t) {
return cmn(bitXOR(c, bitOR(b, (~d))), a, b, x, s, t);
}
function doEncode(x:Array<Int>):Array<Int> {
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var step;
var i = 0;
while (i < x.length) {
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
step = 0;
a = ff(a, b, c, d, x[i + 0], 7, -680876936);
d = ff(d, a, b, c, x[i + 1], 12, -389564586);
c = ff(c, d, a, b, x[i + 2], 17, 606105819);
b = ff(b, c, d, a, x[i + 3], 22, -1044525330);
a = ff(a, b, c, d, x[i + 4], 7, -176418897);
d = ff(d, a, b, c, x[i + 5], 12, 1200080426);
c = ff(c, d, a, b, x[i + 6], 17, -1473231341);
b = ff(b, c, d, a, x[i + 7], 22, -45705983);
a = ff(a, b, c, d, x[i + 8], 7, 1770035416);
d = ff(d, a, b, c, x[i + 9], 12, -1958414417);
c = ff(c, d, a, b, x[i + 10], 17, -42063);
b = ff(b, c, d, a, x[i + 11], 22, -1990404162);
a = ff(a, b, c, d, x[i + 12], 7, 1804603682);
d = ff(d, a, b, c, x[i + 13], 12, -40341101);
c = ff(c, d, a, b, x[i + 14], 17, -1502002290);
b = ff(b, c, d, a, x[i + 15], 22, 1236535329);
a = gg(a, b, c, d, x[i + 1], 5, -165796510);
d = gg(d, a, b, c, x[i + 6], 9, -1069501632);
c = gg(c, d, a, b, x[i + 11], 14, 643717713);
b = gg(b, c, d, a, x[i + 0], 20, -373897302);
a = gg(a, b, c, d, x[i + 5], 5, -701558691);
d = gg(d, a, b, c, x[i + 10], 9, 38016083);
c = gg(c, d, a, b, x[i + 15], 14, -660478335);
b = gg(b, c, d, a, x[i + 4], 20, -405537848);
a = gg(a, b, c, d, x[i + 9], 5, 568446438);
d = gg(d, a, b, c, x[i + 14], 9, -1019803690);
c = gg(c, d, a, b, x[i + 3], 14, -187363961);
b = gg(b, c, d, a, x[i + 8], 20, 1163531501);
a = gg(a, b, c, d, x[i + 13], 5, -1444681467);
d = gg(d, a, b, c, x[i + 2], 9, -51403784);
c = gg(c, d, a, b, x[i + 7], 14, 1735328473);
b = gg(b, c, d, a, x[i + 12], 20, -1926607734);
a = hh(a, b, c, d, x[i + 5], 4, -378558);
d = hh(d, a, b, c, x[i + 8], 11, -2022574463);
c = hh(c, d, a, b, x[i + 11], 16, 1839030562);
b = hh(b, c, d, a, x[i + 14], 23, -35309556);
a = hh(a, b, c, d, x[i + 1], 4, -1530992060);
d = hh(d, a, b, c, x[i + 4], 11, 1272893353);
c = hh(c, d, a, b, x[i + 7], 16, -155497632);
b = hh(b, c, d, a, x[i + 10], 23, -1094730640);
a = hh(a, b, c, d, x[i + 13], 4, 681279174);
d = hh(d, a, b, c, x[i + 0], 11, -358537222);
c = hh(c, d, a, b, x[i + 3], 16, -722521979);
b = hh(b, c, d, a, x[i + 6], 23, 76029189);
a = hh(a, b, c, d, x[i + 9], 4, -640364487);
d = hh(d, a, b, c, x[i + 12], 11, -421815835);
c = hh(c, d, a, b, x[i + 15], 16, 530742520);
b = hh(b, c, d, a, x[i + 2], 23, -995338651);
a = ii(a, b, c, d, x[i + 0], 6, -198630844);
d = ii(d, a, b, c, x[i + 7], 10, 1126891415);
c = ii(c, d, a, b, x[i + 14], 15, -1416354905);
b = ii(b, c, d, a, x[i + 5], 21, -57434055);
a = ii(a, b, c, d, x[i + 12], 6, 1700485571);
d = ii(d, a, b, c, x[i + 3], 10, -1894986606);
c = ii(c, d, a, b, x[i + 10], 15, -1051523);
b = ii(b, c, d, a, x[i + 1], 21, -2054922799);
a = ii(a, b, c, d, x[i + 8], 6, 1873313359);
d = ii(d, a, b, c, x[i + 15], 10, -30611744);
c = ii(c, d, a, b, x[i + 6], 15, -1560198380);
b = ii(b, c, d, a, x[i + 13], 21, 1309151649);
a = ii(a, b, c, d, x[i + 4], 6, -145523070);
d = ii(d, a, b, c, x[i + 11], 10, -1120210379);
c = ii(c, d, a, b, x[i + 2], 15, 718787259);
b = ii(b, c, d, a, x[i + 9], 21, -343485551);
a = addme(a, olda);
b = addme(b, oldb);
c = addme(c, oldc);
d = addme(d, oldd);
i += 16;
}
return [a, b, c, d];
}
}

View File

@ -0,0 +1,172 @@
/*
* 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 haxe.crypto;
/**
Creates a Sha1 of a String.
**/
class Sha1 {
public static function encode(s:String):String {
var sh = new Sha1();
var h = sh.doEncode(str2blks(s));
return sh.hex(h);
}
public static function make(b:haxe.io.Bytes):haxe.io.Bytes {
var h = new Sha1().doEncode(bytes2blks(b));
var out = haxe.io.Bytes.alloc(20);
var p = 0;
for (i in 0...5) {
out.set(p++, h[i] >>> 24);
out.set(p++, (h[i] >> 16) & 0xFF);
out.set(p++, (h[i] >> 8) & 0xFF);
out.set(p++, h[i] & 0xFF);
}
return out;
}
function new() {}
function doEncode(x:Array<Int>):Array<Int> {
var w = new Array<Int>();
var a = 0x67452301;
var b = 0xEFCDAB89;
var c = 0x98BADCFE;
var d = 0x10325476;
var e = 0xC3D2E1F0;
var i = 0;
while (i < x.length) {
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
var j = 0;
while (j < 80) {
if (j < 16)
w[j] = x[i + j];
else
w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
var t = rol(a, 5) + ft(j, b, c, d) + e + w[j] + kt(j);
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
j++;
}
a += olda;
b += oldb;
c += oldc;
d += oldd;
e += olde;
i += 16;
}
return [a, b, c, d, e];
}
/**
Convert a string to a sequence of 16-word blocks, stored as an array.
Append padding bits and the length, as described in the SHA1 standard.
**/
static function str2blks(s:String):Array<Int> {
#if target.unicode
var s = haxe.io.Bytes.ofString(s);
#end
var nblk = ((s.length + 8) >> 6) + 1;
var blks = new Array<Int>();
for (i in 0...nblk * 16)
blks[i] = 0;
for (i in 0...s.length) {
var p = i >> 2;
blks[p] |= #if target.unicode s.get(i) #else StringTools.fastCodeAt(s, i) #end << (24 - ((i & 3) << 3));
}
var i = s.length;
var p = i >> 2;
blks[p] |= 0x80 << (24 - ((i & 3) << 3));
blks[nblk * 16 - 1] = s.length * 8;
return blks;
}
static function bytes2blks(b:haxe.io.Bytes):Array<Int> {
var nblk = ((b.length + 8) >> 6) + 1;
var blks = new Array<Int>();
for (i in 0...nblk * 16)
blks[i] = 0;
for (i in 0...b.length) {
var p = i >> 2;
blks[p] |= b.get(i) << (24 - ((i & 3) << 3));
}
var i = b.length;
var p = i >> 2;
blks[p] |= 0x80 << (24 - ((i & 3) << 3));
blks[nblk * 16 - 1] = b.length * 8;
return blks;
}
/**
Bitwise rotate a 32-bit number to the left
**/
inline function rol(num:Int, cnt:Int):Int {
return (num << cnt) | (num >>> (32 - cnt));
}
/**
Perform the appropriate triplet combination function for the current iteration
**/
function ft(t:Int, b:Int, c:Int, d:Int):Int {
if (t < 20)
return (b & c) | ((~b) & d);
if (t < 40)
return b ^ c ^ d;
if (t < 60)
return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/**
Determine the appropriate additive constant for the current iteration
**/
function kt(t:Int):Int {
if (t < 20)
return 0x5A827999;
if (t < 40)
return 0x6ED9EBA1;
if (t < 60)
return 0x8F1BBCDC;
return 0xCA62C1D6;
}
function hex(a:Array<Int>) {
var str = "";
for (num in a) {
str += StringTools.hex(num, 8);
}
return str.toLowerCase();
}
}

View File

@ -0,0 +1,191 @@
/*
* 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 haxe.crypto;
/**
Creates a Sha224 of a String.
**/
class Sha224 {
public static function encode(s:String):String {
var sh = new Sha224();
var h = sh.doEncode(s, s.length * 8);
return sh.hex(h);
}
public static function make(b:haxe.io.Bytes):haxe.io.Bytes {
var h = new Sha224().doEncode(b.toString(), b.length * 8);
var out = haxe.io.Bytes.alloc(28);
var p = 0;
for (i in 0...8) {
out.set(p++, h[i] >>> 24);
out.set(p++, (h[i] >> 16) & 0xFF);
out.set(p++, (h[i] >> 8) & 0xFF);
out.set(p++, h[i] & 0xFF);
}
return out;
}
public function new() {}
function doEncode(str:String, strlen:Int):Array<Int> {
var K:Array<Int> = [
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
];
var HASH:Array<Int> = [
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4
];
var W = new Array<Int>();
W[64] = 0;
var a:Int, b:Int, c:Int, d:Int, e:Int, f:Int, g:Int, h:Int, i:Int, j:Int;
var T1, T2;
var i:Int = 0;
var blocks:Array<Int> = str2blks(str);
blocks[strlen >> 5] |= 0x80 << (24 - strlen % 32);
blocks[((strlen + 64 >> 9) << 4) + 15] = strlen;
while (i < blocks.length) {
a = HASH[0];
b = HASH[1];
c = HASH[2];
d = HASH[3];
e = HASH[4];
f = HASH[5];
g = HASH[6];
h = HASH[7];
for (j in 0...64) {
if (j < 16) {
W[j] = blocks[j + i];
} else {
W[j] = safeAdd(safeAdd(safeAdd(Gamma1(W[j - 2]), W[j - 7]), Gamma0(W[j - 15])), W[j - 16]);
}
T1 = safeAdd(safeAdd(safeAdd(safeAdd(h, Sigma1(e)), Ch(e, f, g)), K[j]), W[j]);
T2 = safeAdd(Sigma0(a), Maj(a, b, c));
h = g;
g = f;
f = e;
e = safeAdd(d, T1);
d = c;
c = b;
b = a;
a = safeAdd(T1, T2);
}
HASH[0] = safeAdd(a, HASH[0]);
HASH[1] = safeAdd(b, HASH[1]);
HASH[2] = safeAdd(c, HASH[2]);
HASH[3] = safeAdd(d, HASH[3]);
HASH[4] = safeAdd(e, HASH[4]);
HASH[5] = safeAdd(f, HASH[5]);
HASH[6] = safeAdd(g, HASH[6]);
HASH[7] = safeAdd(h, HASH[7]);
i += 16;
}
return HASH;
}
static function str2blks(s:String):Array<Int> {
var nblk = ((s.length + 8) >> 6) + 1;
var blks = new Array<Int>();
for (i in 0...nblk * 16)
blks[i] = 0;
for (i in 0...s.length) {
var p = i >> 2;
blks[p] |= s.charCodeAt(i) << (24 - ((i & 3) << 3));
}
var i = s.length;
var p = i >> 2;
blks[p] |= 0x80 << (24 - ((i & 3) << 3));
blks[nblk * 16 - 1] = s.length * 8;
return blks;
}
extern inline static function safeAdd(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >>> 16) + (y >>> 16) + (lsw >>> 16);
return ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
}
// ++
extern inline function ROTR(X, n) {
return (X >>> n) | (X << (32 - n));
}
// ++
extern inline function SHR(X, n) {
return (X >>> n);
}
// ++
extern inline function Ch(x, y, z) {
return ((x & y) ^ ((~x) & z));
}
// ++
extern inline function Maj(x, y, z) {
return ((x & y) ^ (x & z) ^ (y & z));
}
extern inline function Sigma0(x) {
return ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22);
}
extern inline function Sigma1(x) {
return ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25);
}
extern inline function Gamma0(x) {
return ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3);
}
extern inline function Gamma1(x) {
return ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10);
}
function hex(a:Array<Int>) {
var str = "";
for (num in a) {
str += StringTools.hex(num, 8);
}
return str.substring(0, 56).toLowerCase();
}
}

View File

@ -0,0 +1,195 @@
/*
* 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 haxe.crypto;
/**
Creates a Sha256 of a String.
**/
class Sha256 {
public static function encode(s:String):String {
var sh = new Sha256();
var h = sh.doEncode(str2blks(s), s.length * 8);
return sh.hex(h);
}
public static function make(b:haxe.io.Bytes):haxe.io.Bytes {
var h = new Sha256().doEncode(bytes2blks(b), b.length * 8);
var out = haxe.io.Bytes.alloc(32);
var p = 0;
for (i in 0...8) {
out.set(p++, h[i] >>> 24);
out.set(p++, (h[i] >> 16) & 0xFF);
out.set(p++, (h[i] >> 8) & 0xFF);
out.set(p++, h[i] & 0xFF);
}
return out;
}
function new() {}
function doEncode(m:Array<Int>, l:Int):Array<Int> {
var K:Array<Int> = [
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
];
var HASH:Array<Int> = [
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
];
var W = new Array<Int>();
W[64] = 0;
var a:Int, b:Int, c:Int, d:Int, e:Int, f:Int, g:Int, h:Int;
var T1, T2;
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >> 9) << 4) + 15] = l;
var i:Int = 0;
while (i < m.length) {
a = HASH[0];
b = HASH[1];
c = HASH[2];
d = HASH[3];
e = HASH[4];
f = HASH[5];
g = HASH[6];
h = HASH[7];
for (j in 0...64) {
if (j < 16)
W[j] = m[j + i];
else
W[j] = safeAdd(safeAdd(safeAdd(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
T1 = safeAdd(safeAdd(safeAdd(safeAdd(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
T2 = safeAdd(Sigma0256(a), Maj(a, b, c));
h = g;
g = f;
f = e;
e = safeAdd(d, T1);
d = c;
c = b;
b = a;
a = safeAdd(T1, T2);
}
HASH[0] = safeAdd(a, HASH[0]);
HASH[1] = safeAdd(b, HASH[1]);
HASH[2] = safeAdd(c, HASH[2]);
HASH[3] = safeAdd(d, HASH[3]);
HASH[4] = safeAdd(e, HASH[4]);
HASH[5] = safeAdd(f, HASH[5]);
HASH[6] = safeAdd(g, HASH[6]);
HASH[7] = safeAdd(h, HASH[7]);
i += 16;
}
return HASH;
}
/**
Convert a string to a sequence of 16-word blocks, stored as an array.
Append padding bits and the length, as described in the SHA1 standard.
**/
static function str2blks(s:String):Array<Int> {
#if target.unicode
var s = haxe.io.Bytes.ofString(s);
#end
var nblk = ((s.length + 8) >> 6) + 1;
var blks = new Array<Int>();
for (i in 0...nblk * 16)
blks[i] = 0;
for (i in 0...s.length) {
var p = i >> 2;
blks[p] |= #if target.unicode s.get(i) #else s.charCodeAt(i) #end << (24 - ((i & 3) << 3));
}
var i = s.length;
var p = i >> 2;
blks[p] |= 0x80 << (24 - ((i & 3) << 3));
blks[nblk * 16 - 1] = s.length * 8;
return blks;
}
static function bytes2blks(b:haxe.io.Bytes):Array<Int> {
var nblk = ((b.length + 8) >> 6) + 1;
var blks = new Array<Int>();
for (i in 0...nblk * 16)
blks[i] = 0;
for (i in 0...b.length) {
var p = i >> 2;
blks[p] |= b.get(i) << (24 - ((i & 3) << 3));
}
var i = b.length;
var p = i >> 2;
blks[p] |= 0x80 << (24 - ((i & 3) << 3));
blks[nblk * 16 - 1] = b.length * 8;
return blks;
}
extern inline function S(X, n) {
return (X >>> n) | (X << (32 - n));
}
extern inline function R(X, n) {
return (X >>> n);
}
extern inline function Ch(x, y, z) {
return ((x & y) ^ ((~x) & z));
}
extern inline function Maj(x, y, z) {
return ((x & y) ^ (x & z) ^ (y & z));
}
extern inline function Sigma0256(x) {
return (S(x, 2) ^ S(x, 13) ^ S(x, 22));
}
extern inline function Sigma1256(x) {
return (S(x, 6) ^ S(x, 11) ^ S(x, 25));
}
extern inline function Gamma0256(x) {
return (S(x, 7) ^ S(x, 18) ^ R(x, 3));
}
extern inline function Gamma1256(x) {
return (S(x, 17) ^ S(x, 19) ^ R(x, 10));
}
extern inline function safeAdd(x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
function hex(a:Array<Int>) {
var str = "";
for (num in a) {
str += StringTools.hex(num, 8);
}
return str.toLowerCase();
}
}

View File

@ -0,0 +1,551 @@
/*
* 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 haxe.display;
import haxe.display.JsonModuleTypes;
import haxe.display.Position;
import haxe.display.Protocol;
/**
Methods of the JSON-RPC-based `--display` protocol in Haxe 4.
A lot of the methods are *inspired* by the Language Server Protocol, but there is **no** intention to be directly compatible with it.
**/
@:publicFields
class DisplayMethods {
/**
The completion request is sent from the client to Haxe to request code completion.
Haxe automatically determines the type of completion to use based on the passed position, see `CompletionResultKind`.
**/
static inline var Completion = new HaxeRequestMethod<CompletionParams, CompletionResult>("display/completion");
/**
The request is sent from the client to Haxe to resolve additional information for a given completion item.
**/
static inline var CompletionItemResolve = new HaxeRequestMethod<CompletionItemResolveParams, CompletionItemResolveResult>("display/completionItem/resolve");
/**
The find references request is sent from the client to Haxe to find locations that reference the symbol at a given text document position.
**/
static inline var FindReferences = new HaxeRequestMethod<FindReferencesParams, GotoDefinitionResult>("display/references");
/**
The goto definition request is sent from the client to Haxe to resolve the definition location(s) of a symbol at a given text document position.
**/
static inline var GotoDefinition = new HaxeRequestMethod<PositionParams, GotoDefinitionResult>("display/definition");
/**
The goto implementation request is sent from the client to Haxe to resolve the implementation location(s) of a symbol at a given text document position.
**/
static inline var GotoImplementation = new HaxeRequestMethod<PositionParams, GotoDefinitionResult>("display/implementation");
/**
The goto type definition request is sent from the client to Haxe to resolve the type definition location(s) of a symbol at a given text document position.
**/
static inline var GotoTypeDefinition = new HaxeRequestMethod<PositionParams, GotoTypeDefinitionResult>("display/typeDefinition");
/**
The hover request is sent from the client to Haxe to request hover information at a given text document position.
**/
static inline var Hover = new HaxeRequestMethod<PositionParams, HoverResult>("display/hover");
/**
This request is sent from the client to Haxe to determine the package for a given file, based on class paths configuration.
**/
static inline var DeterminePackage = new HaxeRequestMethod<FileParams, DeterminePackageResult>("display/package");
/**
The signature help request is sent from the client to Haxe to request signature information at a given cursor position.
**/
static inline var SignatureHelp = new HaxeRequestMethod<SignatureHelpParams, SignatureHelpResult>("display/signatureHelp");
/*
TODO:
- finish completion
- diagnostics
- codeLens
- workspaceSymbols ("project/symbol"?)
*/
}
/** Completion **/
typedef CompletionParams = PositionParams & {
var wasAutoTriggered:Bool;
/** list of metas to include in responses **/
var ?meta:Array<String>;
}
typedef FieldResolution = {
/**
Whether it's valid to use the unqualified name of the field or not.
This is `false` if the identifier is shadowed.
**/
var isQualified:Bool;
/**
The qualifier that has to be inserted to use the field if `!isQualified`.
Can either be `this` or `super` for instance fields for the type name for `static` fields.
**/
var qualifier:String;
}
typedef DisplayLocal<T> = {
var id:Int;
var name:String;
var type:JsonType<T>;
var origin:LocalOrigin;
var capture:Bool;
var ?extra:{
var params:Array<JsonTypeParameter>;
var expr:JsonExpr;
};
var meta:JsonMetadata;
var pos:JsonPos;
var isInline:Bool;
var isFinal:Bool;
}
enum abstract LocalOrigin(Int) {
var LocalVariable;
var Argument;
var ForVariable;
var PatternVariable;
var CatchVariable;
var LocalFunction;
}
enum abstract ClassFieldOriginKind<T>(Int) {
/**
The field is declared on the current type itself.
**/
var Self:ClassFieldOriginKind<JsonModuleType<T>>;
/**
The field is a static field brought into context via a static import
(`import pack.Module.Type.field`).
**/
var StaticImport:ClassFieldOriginKind<JsonModuleType<T>>;
/**
The field is declared on a parent type, such as:
- a super class field that is not overriden
- a forwarded abstract field
**/
var Parent:ClassFieldOriginKind<JsonModuleType<T>>;
/**
The field is a static extension method brought
into context with the `using` keyword.
**/
var StaticExtension:ClassFieldOriginKind<JsonModuleType<T>>;
/**
This field doesn't belong to any named type, just an anonymous structure.
**/
var AnonymousStructure:ClassFieldOriginKind<JsonAnon>;
/**
Special fields built into the compiler, such as:
- `code` on single-character Strings
- `bind()` on functions.
**/
var BuiltIn:ClassFieldOriginKind<NoData>;
/**
The origin of this class field is unknown.
**/
var Unknown:ClassFieldOriginKind<NoData>;
}
typedef ClassFieldOrigin<T> = {
var kind:ClassFieldOriginKind<T>;
var ?args:T;
}
typedef ClassFieldOccurrence<T> = {
var field:JsonClassField;
var resolution:FieldResolution;
var ?origin:ClassFieldOrigin<T>;
}
enum abstract EnumFieldOriginKind<T>(Int) {
/**
The enum value is declared on the current type itself.
**/
var Self:EnumFieldOriginKind<JsonModuleType<T>>;
/**
The enum value is brought into context via a static import
(`import pack.Module.Enum.Value`).
**/
var StaticImport:EnumFieldOriginKind<JsonModuleType<T>>;
}
typedef EnumFieldOrigin<T> = {
var kind:EnumFieldOriginKind<T>;
var ?args:T;
}
typedef EnumFieldOccurrence<T> = {
var field:JsonEnumField;
var resolution:FieldResolution;
var ?origin:EnumFieldOrigin<T>;
}
enum abstract Literal(String) {
var Null = "null";
var True = "true";
var False = "false";
var This = "this";
var Trace = "trace";
}
enum abstract DisplayModuleTypeKind(Int) {
var Class;
var Interface;
var Enum;
var Abstract;
var EnumAbstract;
/** A `typedef` that is just an alias for another type. **/
var TypeAlias;
/** A `typedef` that is an alias for an anonymous structure. **/
var Struct;
/** A type name introduced by `import as` / `import in` **/
// var ImportAlias;
}
typedef DisplayModuleType = {
var path:JsonTypePath;
var pos:JsonPos;
var isPrivate:Bool;
var params:Array<DisplayModuleTypeParameter>;
var meta:JsonMetadata;
var doc:JsonDoc;
var isExtern:Bool;
var isFinal:Bool;
var isAbstract:Bool;
var kind:DisplayModuleTypeKind;
}
typedef DisplayModuleTypeParameter = {
var name:String;
var meta:JsonMetadata;
var constraints:Array<JsonType<Dynamic>>;
}
typedef DisplayLiteral<T> = {
var name:String;
}
enum abstract MetadataTarget(String) {
var Class = "TClass";
var ClassField = "TClassField";
var Abstract = "TAbstract";
var AbstractField = "TAbstractField";
var Enum = "TEnum";
var Typedef = "TTypedef";
var AnyField = "TAnyField";
var Expr = "TExpr";
var TypeParameter = "TTypeParameter";
}
enum abstract Platform(String) {
var Cross = "cross";
var Js = "js";
var Lua = "lua";
var Neko = "neko";
var Flash = "flash";
var Php = "php";
var Cpp = "cpp";
var Cs = "cs";
var Java = "java";
var Python = "python";
var Hl = "hl";
var Eval = "eval";
}
typedef Metadata = {
var name:String;
var doc:JsonDoc;
var parameters:Array<String>;
var platforms:Array<Platform>;
var targets:Array<MetadataTarget>;
var internal:Bool;
var ?links:Array<String>;
}
typedef Define = {
var name:String;
var value:Null<String>;
var doc:JsonDoc;
var parameters:Array<String>;
var platforms:Array<Platform>;
var links:Array<String>;
}
typedef Keyword = {
var name:KeywordKind;
}
enum abstract KeywordKind(String) to String {
var Implements = "implements";
var Extends = "extends";
var Function = "function";
var Var = "var";
var If = "if";
var Else = "else";
var While = "while";
var Do = "do";
var For = "for";
var Break = "break";
var Return = "return";
var Continue = "continue";
var Switch = "switch";
var Case = "case";
var Default = "default";
var Try = "try";
var Catch = "catch";
var New = "new";
var Throw = "throw";
var Untyped = "untyped";
var Cast = "cast";
var Macro = "macro";
var Package = "package";
var Import = "import";
var Using = "using";
var Public = "public";
var Private = "private";
var Static = "static";
var Extern = "extern";
var Dynamic = "dynamic";
var Override = "override";
var Overload = "overload";
var Class = "class";
var Interface = "interface";
var Enum = "enum";
var Abstract = "abstract";
var Typedef = "typedef";
var Final = "final";
var Inline = "inline";
}
/* enum abstract PackageContentKind(Int) {
var Module;
var Package;
}*/
typedef Package = {
var path:JsonPackagePath;
// var ?contents:Array<{name:String, kind:PackageContentKind}>;
}
typedef Module = {
var path:JsonModulePath;
// var ?contents:Array<ModuleType>;
}
enum abstract DisplayItemKind<T>(String) {
var Local:DisplayItemKind<DisplayLocal<Dynamic>>;
var ClassField:DisplayItemKind<ClassFieldOccurrence<Dynamic>>;
var EnumField:DisplayItemKind<EnumFieldOccurrence<Dynamic>>;
/** Only for the enum values in enum abstracts, other fields use `ClassField`. **/
var EnumAbstractField:DisplayItemKind<ClassFieldOccurrence<Dynamic>>;
var Type:DisplayItemKind<DisplayModuleType>;
var Package:DisplayItemKind<Package>;
var Module:DisplayItemKind<Module>;
var Literal:DisplayItemKind<DisplayLiteral<Dynamic>>;
var Metadata:DisplayItemKind<Metadata>;
var Keyword:DisplayItemKind<Keyword>;
var AnonymousStructure:DisplayItemKind<JsonAnon>;
var Expression:DisplayItemKind<JsonTExpr>;
var TypeParameter:DisplayItemKind<DisplayModuleTypeParameter>;
var Define:DisplayItemKind<Define>;
}
typedef DisplayItem<T> = {
var kind:DisplayItemKind<T>;
var args:T;
var ?type:JsonType<Dynamic>;
var ?index:Int;
}
typedef DisplayItemOccurrence<T> = {
var range:Range;
var item:DisplayItem<T>;
var ?moduleType:JsonModuleType<Dynamic>;
var ?moduleTypeFollowed:JsonModuleType<Dynamic>;
}
typedef FieldCompletionSubject<T> = DisplayItemOccurrence<T> & {
var ?iterator:{
var type:JsonType<Dynamic>;
};
var ?keyValueIterator:{
var key:JsonType<Dynamic>;
var value:JsonType<Dynamic>;
};
}
typedef ToplevelCompletion<T> = {
var ?expectedType:JsonType<T>;
var ?expectedTypeFollowed:JsonType<T>;
var ?compatibleTypes:Array<JsonType<Dynamic>>;
}
typedef StructExtensionCompletion = {
var isIntersectionType:Bool;
}
typedef PatternCompletion<T> = ToplevelCompletion<T> & {
var isOutermostPattern:Bool;
}
enum abstract CompletionModeKind<T>(Int) {
var Field:CompletionModeKind<FieldCompletionSubject<Dynamic>>;
var StructureField;
var Toplevel:CompletionModeKind<ToplevelCompletion<Dynamic>>;
var Metadata;
var TypeHint;
var Extends;
var Implements;
var StructExtension:CompletionModeKind<StructExtensionCompletion>;
var Import;
var Using;
var New;
var Pattern:CompletionModeKind<PatternCompletion<Dynamic>>;
var Override;
var TypeRelation;
var TypeDeclaration;
}
typedef CompletionMode<T> = {
var kind:CompletionModeKind<T>;
var ?args:T;
}
typedef CompletionResponse<T1, T2> = {
var items:Array<DisplayItem<T1>>;
var mode:CompletionMode<T2>;
var ?replaceRange:Range;
var ?isIncomplete:Bool;
var ?filterString:String;
}
typedef CompletionResult = Response<Null<CompletionResponse<Dynamic, Dynamic>>>;
/** CompletionItem Resolve **/
typedef CompletionItemResolveParams = {
var index:Int;
};
typedef CompletionItemResolveResult = Response<{
var item:DisplayItem<Dynamic>;
}>;
/** FindReferences **/
typedef FindReferencesParams = PositionParams & {
var ?kind:FindReferencesKind;
}
enum abstract FindReferencesKind(String) to String {
/**
Find only direct references to the requested symbol.
Does not look for references to parent or overriding methods.
**/
var Direct = "direct";
/**
Find references to the base field and all the overidding fields in the inheritance chain.
**/
var WithBaseAndDescendants = "withBaseAndDescendants";
/**
Find references to the requested field and references to all
descendants of the requested field.
**/
var WithDescendants = "withDescendants";
}
/** GotoDefinition **/
typedef GotoDefinitionResult = Response<Array<Location>>;
/** GotoTypeDefinition **/
typedef GotoTypeDefinitionResult = Response<Array<Location>>;
/** Hover **/
typedef HoverResult = Response<Null<HoverDisplayItemOccurence<Dynamic>>>;
typedef HoverDisplayItemOccurence<T> = DisplayItemOccurrence<T> & {
var ?expected:{
var ?type:JsonType<Dynamic>;
var ?name:{
var name:String;
var kind:HoverExpectedNameKind;
var ?doc:String;
};
};
}
enum abstract HoverExpectedNameKind(Int) {
var FunctionArgument;
var StructureField;
}
/** DeterminePackage **/
typedef DeterminePackageResult = Response<Array<String>>;
/** SignatureHelp **/
typedef SignatureHelpParams = PositionParams & {
var wasAutoTriggered:Bool;
}
typedef SignatureInformation = JsonFunctionSignature & {
var ?documentation:String;
}
enum abstract SignatureItemKind(Int) {
var Call;
var ArrayAccess;
}
typedef SignatureItem = {
var signatures:Array<SignatureInformation>;
var activeSignature:Int;
var activeParameter:Int;
var kind:SignatureItemKind;
}
typedef SignatureHelpResult = Response<Null<SignatureItem>>;
/** General types **/
typedef PositionParams = FileParams & {
/** Unicode character offset in the file. **/
var offset:Int;
var ?contents:String;
}

View File

@ -0,0 +1,33 @@
/*
* 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 haxe.display;
abstract FsPath(String) {
public inline function new(path:String) {
this = path;
}
public inline function toString():String {
return this;
}
}

View File

@ -0,0 +1,375 @@
/*
* 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 haxe.display;
typedef JsonTodo = Dynamic;
typedef JsonPos = {
var file:String;
var min:Int;
var max:Int;
}
typedef JsonDoc = Null<String>;
enum abstract ImportStatus(Int) {
/**
This type is already available with it's unqualified name for one of these reasons:
- it's a toplevel type
- it's imported with an `import` in the current module
- it's imported in an `import.hx` file
**/
var Imported;
/**
The type is currently not imported. It can be accessed either
with its fully qualified name or by inserting an import.
**/
var Unimported;
/**
A type with the same name is already imported in the module.
The fully qualified name has to be used to access it.
**/
var Shadowed;
}
/* Type instance */
typedef JsonPackagePath = {
var pack:Array<String>;
}
typedef JsonModulePath = JsonPackagePath & {
var moduleName:String;
var ?importStatus:ImportStatus;
}
typedef JsonTypePath = JsonModulePath & {
var typeName:String;
}
typedef JsonStaticFieldPath = JsonTypePath & {
var fieldName:String;
}
typedef JsonTypePathWithParams = {
var path:JsonTypePath;
var params:JsonTypes;
}
typedef JsonFunctionArgument = {
var name:String;
var opt:Bool;
var t:JsonType<Dynamic>;
var ?value:{
var string:String;
};
}
typedef JsonFunctionSignature = {
var args:Array<JsonFunctionArgument>;
var ret:JsonType<Dynamic>;
}
enum abstract JsonAnonStatusKind<T>(String) {
var AClosed;
var AOpened;
var AConst;
var AExtend:JsonAnonStatusKind<JsonTypes>;
var AClassStatics:JsonAnonStatusKind<JsonTypePath>;
var AEnumStatics:JsonAnonStatusKind<JsonTypePath>;
var AAbstractStatics:JsonAnonStatusKind<JsonTypePath>;
}
typedef JsonAnonStatus<T> = {
var kind:JsonAnonStatusKind<T>;
var args:T;
}
typedef JsonAnon = {
var fields:JsonClassFields;
var status:JsonAnonStatus<Dynamic>;
}
enum abstract JsonTypeKind<T>(String) {
var TMono;
var TInst:JsonTypeKind<JsonTypePathWithParams>;
var TEnum:JsonTypeKind<JsonTypePathWithParams>;
var TType:JsonTypeKind<JsonTypePathWithParams>;
var TAbstract:JsonTypeKind<JsonTypePathWithParams>;
var TFun:JsonTypeKind<JsonFunctionSignature>;
var TAnonymous:JsonTypeKind<JsonAnon>;
var TDynamic:JsonTypeKind<Null<JsonType<Dynamic>>>;
}
typedef JsonType<T> = {
var kind:JsonTypeKind<T>;
var args:T;
}
typedef JsonTypes = Array<JsonType<Dynamic>>;
/* Type parameters */
typedef JsonTypeParameter = {
var name:String;
var constraints:JsonTypes;
}
typedef JsonTypeParameters = Array<JsonTypeParameter>;
/* Expr */
enum abstract JsonBinopKind<T>(String) {
var OpAdd;
var OpMult;
var OpDiv;
var OpSub;
var OpAssign;
var OpEq;
var OpNotEq;
var OpGt;
var OpGte;
var OpLt;
var OpLte;
var OpAnd;
var OpOr;
var OpXor;
var OpBoolAnd;
var OpBoolOr;
var OpShl;
var OpShr;
var OpUShr;
var OpMod;
var OpAssignOp:JsonBinopKind<JsonBinop<Dynamic>>;
var OpInterval;
var OpArrow;
var OpIn;
}
typedef JsonBinop<T> = {
var kind:JsonBinopKind<T>;
var args:T;
}
enum abstract JsonUnop(String) {
var OpIncrement;
var OpDecrement;
var OpNot;
var OpNeg;
var OpNegBits;
}
typedef JsonExpr = JsonTodo;
typedef JsonMetadataEntry = {
var name:String;
var args:Array<JsonExpr>;
var pos:JsonPos;
}
typedef JsonMetadata = Array<JsonMetadataEntry>;
enum abstract JsonTConstantKind<T>(String) {
var TInt:JsonTConstantKind<String>;
var TFloat:JsonTConstantKind<String>;
var TString:JsonTConstantKind<String>;
var TBool:JsonTConstantKind<Bool>;
var TNull;
var TThis;
var TSuper;
}
typedef JsonTConstant<T> = {
var kind:JsonTConstantKind<T>;
var args:T;
}
typedef JsonTExpr = JsonTodo;
/* Fields */
enum abstract JsonVarAccessKind<T>(String) {
var AccNormal;
var AccNo;
var AccNever;
var AccResolve;
var AccCall;
var AccInline;
var AccRequire:JsonVarAccessKind<{require:String, message:Null<String>}>;
var AccCtor;
}
typedef JsonVarAccess<T> = {
var kind:JsonVarAccessKind<T>;
var args:T;
}
enum abstract JsonMethodKind(String) {
var MethNormal;
var MethInline;
var MethDynamic;
var MethMacro;
}
enum abstract JsonFieldKindKind<T>(String) {
var FVar:JsonFieldKindKind<{read:JsonVarAccess<Dynamic>, write:JsonVarAccess<Dynamic>}>;
var FMethod:JsonFieldKindKind<JsonMethodKind>;
}
typedef JsonFieldKind<T> = {
var kind:JsonFieldKindKind<T>;
var args:T;
}
enum abstract JsonClassFieldScope(Int) {
var Static;
var Member;
var Constructor;
}
typedef JsonClassField = {
var name:String;
var type:JsonType<Dynamic>;
var isPublic:Bool;
var isFinal:Bool;
var isAbstract:Bool;
var params:JsonTypeParameters;
var meta:JsonMetadata;
var kind:JsonFieldKind<Dynamic>;
var ?expr:{
var string:String;
};
var pos:JsonPos;
var doc:JsonDoc;
var overloads:JsonClassFields;
var scope:JsonClassFieldScope;
}
typedef JsonClassFields = Array<JsonClassField>;
typedef JsonClassFieldReference = String;
typedef JsonEnumField = {
var name:String;
var type:JsonType<Dynamic>;
var pos:JsonPos;
var meta:JsonMetadata;
var index:Int;
var doc:JsonDoc;
var params:JsonTypeParameters;
}
typedef JsonEnumFields = Array<JsonEnumField>;
/* Class */
enum abstract JsonClassKindKind<T>(String) {
var KNormal;
var KTypeParameter:JsonClassKindKind<JsonTypes>;
var KExtension:JsonClassKindKind<JsonTypePathWithParams>;
var KExpr:JsonClassKindKind<JsonExpr>;
var KGeneric;
var KGenericInstance:JsonClassKindKind<JsonTypePathWithParams>;
var KMacroType;
var KAbstractImpl:JsonClassKindKind<JsonTypePath>;
var KGenericBuild;
var KModuleFields:JsonClassKindKind<JsonModulePath>;
}
typedef JsonClassKind<T> = {
var kind:JsonClassKindKind<T>;
var args:T;
}
typedef JsonClass = {
var kind:JsonClassKind<Dynamic>;
var isInterface:Bool;
var isExtern:Bool;
var isFinal:Bool;
var isAbstract:Bool;
var superClass:Null<JsonTypePathWithParams>;
var interfaces:Array<JsonTypePathWithParams>;
var fields:JsonClassFields;
var statics:JsonClassFields;
var constructor:Null<JsonClassField>;
var init:Null<JsonTExpr>;
var overrides:Array<JsonClassFieldReference>;
}
/* Enum */
typedef JsonEnum = {
var constructors:JsonEnumFields;
var isExtern:Bool;
}
/* Typedef */
typedef JsonTypedef = {
var type:JsonType<Dynamic>;
}
/* Abstract */
typedef JsonAbstractBinop = {
var op:JsonBinop<Dynamic>;
var field:JsonClassFieldReference;
}
typedef JsonAbstractUnop = {
var op:JsonUnop;
var postFix:Bool;
var field:JsonClassFieldReference;
}
typedef JsonAbstractCast = {
var t:JsonType<Dynamic>;
var field:JsonClassFieldReference;
}
typedef JsonAbstract = {
var type:JsonType<Dynamic>;
var impl:Null<JsonClass>;
var binops:Array<JsonAbstractBinop>;
var unops:Array<JsonAbstractUnop>;
var from:Array<JsonAbstractCast>;
var to:Array<JsonAbstractCast>;
var array:JsonClassFields;
var resolve:Null<JsonClassFieldReference>;
}
/* Module type */
enum abstract JsonModuleTypeKind<T>(String) {
var Class:JsonModuleTypeKind<JsonClass> = "class";
var Enum:JsonModuleTypeKind<JsonEnum> = "enum";
var Typedef:JsonModuleTypeKind<JsonTypedef> = "typedef";
var Abstract:JsonModuleTypeKind<JsonAbstract> = "abstract";
}
typedef JsonModuleType<T> = {
var pack:Array<String>;
var name:String;
var moduleName:String;
var pos:JsonPos;
var isPrivate:Bool;
var params:JsonTypeParameters;
var meta:JsonMetadata;
var doc:JsonDoc;
var kind:JsonModuleTypeKind<T>;
var args:T;
}
typedef JsonModuleTypes = Array<JsonModuleType<Dynamic>>;

View File

@ -0,0 +1,61 @@
/*
* 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 haxe.display;
/**
Position in a text document expressed as 1-based line and character offset.
**/
typedef Position = {
/**
Line position in a document (1-based).
**/
var line:Int;
/**
Character offset on a line in a document (1-based).
**/
var character:Int;
}
/**
A range in a text document expressed as (1-based) start and end positions.
**/
typedef Range = {
/**
The range's start position
**/
var start:Position;
/**
The range's end position
**/
var end:Position;
}
/**
Represents a location inside a resource, such as a line inside a text file.
**/
typedef Location = {
var file:FsPath;
var range:Range;
}

View File

@ -0,0 +1,111 @@
/*
* 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 haxe.display;
import haxe.display.Position;
@:publicFields
class Methods {
/**
The initialize request is sent from the client to Haxe to determine the capabilities.
**/
static inline var Initialize = new HaxeRequestMethod<InitializeParams, InitializeResult>("initialize");
}
/* Initialize */
typedef InitializeParams = {
final ?supportsResolve:Bool;
/** dot paths to exclude from readClassPaths / toplevel completion **/
final ?exclude:Array<String>;
/** The maximum number of completion items to return **/
final ?maxCompletionItems:Int;
}
/**
Represents a semantic version, see https://semver.org/.
**/
typedef Version = {
final major:Int;
final minor:Int;
final patch:Int;
final ?pre:String;
final ?build:String;
}
typedef InitializeResult = Response<{
final protocolVersion:Version;
final haxeVersion:Version;
final methods:Array<String>;
}>;
/* general protocol types */
typedef Timer = {
final name:String;
final time:Float;
final ?path:String;
final ?info:String;
final ?calls:Int;
final ?percentTotal:Float;
final ?percentParent:Float;
final ?children:Array<Timer>;
}
typedef Response<T> = {
final ?result:T;
/** UNIX timestamp at the moment the data was sent. **/
final ?timestamp:Float;
/** Only sent if `--times` is enabled. **/
final ?timers:Timer;
}
typedef FileParams = {
var file:FsPath;
}
abstract HaxeRequestMethod<TParams, TResponse>(String) to String {
public inline function new(method:String)
this = method;
}
abstract HaxeNotificationMethod<TParams>(String) to String {
public inline function new(method:String)
this = method;
}
typedef HaxeResponseErrorData = Array<{
var severity:HaxeResponseErrorSeverity;
var ?location:Location;
var message:String;
}>;
enum abstract HaxeResponseErrorSeverity(Int) {
var Error = 1;
var Warning;
var Hint;
}
enum NoData {}

View File

@ -0,0 +1,167 @@
/*
* 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 haxe.display;
import haxe.display.JsonModuleTypes;
import haxe.display.Position;
import haxe.display.Protocol;
@:publicFields
class ServerMethods {
/**
This request is sent from the client to Haxe to explore the class paths. This effectively creates a cache for toplevel completion.
**/
static inline var ReadClassPaths = new HaxeRequestMethod<NoData, Response<{?files:Int}>>("server/readClassPaths");
static inline var Configure = new HaxeRequestMethod<ConfigureParams, Response<NoData>>("server/configure");
static inline var Invalidate = new HaxeRequestMethod<FileParams, Response<NoData>>("server/invalidate");
static inline var Contexts = new HaxeRequestMethod<NoData, Response<Array<HaxeServerContext>>>("server/contexts");
static inline var Memory = new HaxeRequestMethod<NoData, Response<HaxeMemoryResult>>("server/memory");
static inline var ContextMemory = new HaxeRequestMethod<ContextParams, Response<HaxeContextMemoryResult>>("server/memory/context");
static inline var ModuleMemory = new HaxeRequestMethod<ModuleParams, Response<HaxeModuleMemoryResult>>("server/memory/module");
static inline var Modules = new HaxeRequestMethod<ContextParams, Response<Array<String>>>("server/modules");
static inline var Module = new HaxeRequestMethod<ModuleParams, Response<JsonModule>>("server/module");
static inline var Files = new HaxeRequestMethod<ContextParams, Response<Array<JsonServerFile>>>("server/files");
static inline var ModuleCreated = new HaxeRequestMethod<FileParams, Response<NoData>>("server/moduleCreated");
}
/* Configure */
typedef ConfigurePrintParams = {
var ?addedDirectory:Bool;
var ?foundDirectories:Bool;
var ?changedDirectories:Bool;
var ?modulePathChanged:Bool;
var ?notCached:Bool;
var ?parsed:Bool;
var ?removedDirectory:Bool;
var ?reusing:Bool;
var ?skippingDep:Bool;
var ?unchangedContent:Bool;
var ?cachedModules:Bool;
var ?arguments:Bool;
var ?completion:Bool;
var ?defines:Bool;
var ?signature:Bool;
var ?displayPosition:Bool;
var ?stats:Bool;
var ?message:Bool;
var ?socketMessage:Bool;
var ?uncaughtError:Bool;
var ?newContext:Bool;
}
typedef ConfigureParams = {
final ?noModuleChecks:Bool;
final ?legacyCompletion:Bool;
final ?print:ConfigurePrintParams;
}
/* Contexts */
typedef HaxeServerContext = {
final index:Int;
final desc:String;
final signature:String;
final platform:String;
final classPaths:Array<String>;
final defines:Array<{key:String, value:String}>;
}
typedef ModuleId = {
final path:String;
final sign:String;
}
typedef JsonModule = {
final id:Int;
final path:JsonModulePath;
final types:Array<JsonTypePath>;
final file:String;
final sign:String;
final dependencies:Array<ModuleId>;
}
typedef JsonServerFile = {
final file:String;
final time:Float;
final pack:String;
final moduleName:Null<String>;
}
/* Memory */
typedef HaxeMemoryResult = {
final contexts:Array<{
final context:HaxeServerContext;
final size:Int;
}>;
final memory:{
final totalCache:Int;
final contextCache:Int;
final haxelibCache:Int;
final directoryCache:Int;
final nativeLibCache:Int;
final ?additionalSizes:Array<{name:String, size:Int}>;
}
}
typedef HaxeContextMemoryResult = {
final moduleCache:{
final size:Int;
final list:Array<{
final path:String;
final size:Int;
final hasTypes:Bool;
}>;
};
final syntaxCache:{
final size:Int;
};
final ?leaks:Array<{
final path:String;
final leaks:Array<{
final path:String;
}>;
}>;
}
typedef HaxeModuleMemoryResult = {
final moduleExtra:Int;
final types:Array<{
final name:String;
final ?pos:Location;
final size:Int;
final fields:Array<{
final name:String;
final ?pos:Location;
final size:Int;
}>;
}>;
}
typedef ContextParams = {
final signature:String;
}
typedef ModuleParams = ContextParams & {
final path:String;
}

View File

@ -0,0 +1,162 @@
/*
* 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 haxe.ds;
/**
ArraySort provides a stable implementation of merge sort through its `sort`
method. It should be used instead of `Array.sort` in cases where the order
of equal elements has to be retained on all targets.
**/
class ArraySort {
/**
Sorts Array `a` according to the comparison function `cmp`, where
`cmp(x,y)` returns 0 if `x == y`, a positive Int if `x > y` and a
negative Int if `x < y`.
This operation modifies Array `a` in place.
This operation is stable: The order of equal elements is preserved.
If `a` or `cmp` are null, the result is unspecified.
**/
static public function sort<T>(a:Array<T>, cmp:T->T->Int) {
rec(a, cmp, 0, a.length);
}
static function rec<T>(a:Array<T>, cmp, from, to) {
var middle = (from + to) >> 1;
if (to - from < 12) {
if (to <= from)
return;
for (i in (from + 1)...to) {
var j = i;
while (j > from) {
if (compare(a, cmp, j, j - 1) < 0)
swap(a, j - 1, j);
else
break;
j--;
}
}
return;
}
rec(a, cmp, from, middle);
rec(a, cmp, middle, to);
doMerge(a, cmp, from, middle, to, middle - from, to - middle);
}
static function doMerge<T>(a:Array<T>, cmp, from, pivot, to, len1, len2) {
var first_cut, second_cut, len11, len22, new_mid;
if (len1 == 0 || len2 == 0)
return;
if (len1 + len2 == 2) {
if (compare(a, cmp, pivot, from) < 0)
swap(a, pivot, from);
return;
}
if (len1 > len2) {
len11 = len1 >> 1;
first_cut = from + len11;
second_cut = lower(a, cmp, pivot, to, first_cut);
len22 = second_cut - pivot;
} else {
len22 = len2 >> 1;
second_cut = pivot + len22;
first_cut = upper(a, cmp, from, pivot, second_cut);
len11 = first_cut - from;
}
rotate(a, cmp, first_cut, pivot, second_cut);
new_mid = first_cut + len22;
doMerge(a, cmp, from, first_cut, new_mid, len11, len22);
doMerge(a, cmp, new_mid, second_cut, to, len1 - len11, len2 - len22);
}
static function rotate<T>(a:Array<T>, cmp:T->T->Int, from, mid, to) {
var n;
if (from == mid || mid == to)
return;
n = gcd(to - from, mid - from);
while (n-- != 0) {
var val = a[from + n];
var shift = mid - from;
var p1 = from + n, p2 = from + n + shift;
while (p2 != from + n) {
a[p1] = a[p2];
p1 = p2;
if (to - p2 > shift)
p2 += shift;
else
p2 = from + (shift - (to - p2));
}
a[p1] = val;
}
}
static function gcd(m, n) {
while (n != 0) {
var t = m % n;
m = n;
n = t;
}
return m;
}
static function upper<T>(a:Array<T>, cmp, from, to, val) {
var len = to - from, half, mid;
while (len > 0) {
half = len >> 1;
mid = from + half;
if (compare(a, cmp, val, mid) < 0)
len = half;
else {
from = mid + 1;
len = len - half - 1;
}
}
return from;
}
static function lower<T>(a:Array<T>, cmp, from, to, val) {
var len = to - from, half, mid;
while (len > 0) {
half = len >> 1;
mid = from + half;
if (compare(a, cmp, mid, val) < 0) {
from = mid + 1;
len = len - half - 1;
} else
len = half;
}
return from;
}
static function swap<T>(a:Array<T>, i, j) {
var tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
static inline function compare<T>(a:Array<T>, cmp:T->T->Int, i, j) {
return cmp(a[i], a[j]);
}
}

View File

@ -0,0 +1,269 @@
/*
* 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 haxe.ds;
/**
BalancedTree allows key-value mapping with arbitrary keys, as long as they
can be ordered. By default, `Reflect.compare` is used in the `compare`
method, which can be overridden in subclasses.
Operations have a logarithmic average and worst-case cost.
Iteration over keys and values, using `keys` and `iterator` respectively,
are in-order.
**/
class BalancedTree<K, V> implements haxe.Constraints.IMap<K, V> {
var root:TreeNode<K, V>;
/**
Creates a new BalancedTree, which is initially empty.
**/
public function new() {}
/**
Binds `key` to `value`.
If `key` is already bound to a value, that binding disappears.
If `key` is null, the result is unspecified.
**/
public function set(key:K, value:V) {
root = setLoop(key, value, root);
}
/**
Returns the value `key` is bound to.
If `key` is not bound to any value, `null` is returned.
If `key` is null, the result is unspecified.
**/
public function get(key:K):Null<V> {
var node = root;
while (node != null) {
var c = compare(key, node.key);
if (c == 0)
return node.value;
if (c < 0)
node = node.left;
else
node = node.right;
}
return null;
}
/**
Removes the current binding of `key`.
If `key` has no binding, `this` BalancedTree is unchanged and false is
returned.
Otherwise the binding of `key` is removed and true is returned.
If `key` is null, the result is unspecified.
**/
public function remove(key:K) {
try {
root = removeLoop(key, root);
return true;
} catch (e:String) {
return false;
}
}
/**
Tells if `key` is bound to a value.
This method returns true even if `key` is bound to null.
If `key` is null, the result is unspecified.
**/
public function exists(key:K) {
var node = root;
while (node != null) {
var c = compare(key, node.key);
if (c == 0)
return true;
else if (c < 0)
node = node.left;
else
node = node.right;
}
return false;
}
/**
Iterates over the bound values of `this` BalancedTree.
This operation is performed in-order.
**/
public function iterator():Iterator<V> {
var ret = [];
iteratorLoop(root, ret);
return ret.iterator();
}
/**
See `Map.keyValueIterator`
**/
@:runtime public inline function keyValueIterator():KeyValueIterator<K, V> {
return new haxe.iterators.MapKeyValueIterator(this);
}
/**
Iterates over the keys of `this` BalancedTree.
This operation is performed in-order.
**/
public function keys():Iterator<K> {
var ret = [];
keysLoop(root, ret);
return ret.iterator();
}
public function copy():BalancedTree<K, V> {
var copied = new BalancedTree<K, V>();
copied.root = root;
return copied;
}
function setLoop(k:K, v:V, node:TreeNode<K, V>) {
if (node == null)
return new TreeNode<K, V>(null, k, v, null);
var c = compare(k, node.key);
return if (c == 0) new TreeNode<K, V>(node.left, k, v, node.right, node.get_height()); else if (c < 0) {
var nl = setLoop(k, v, node.left);
balance(nl, node.key, node.value, node.right);
} else {
var nr = setLoop(k, v, node.right);
balance(node.left, node.key, node.value, nr);
}
}
function removeLoop(k:K, node:TreeNode<K, V>) {
if (node == null)
throw "Not_found";
var c = compare(k, node.key);
return if (c == 0) merge(node.left,
node.right); else if (c < 0) balance(removeLoop(k, node.left), node.key, node.value,
node.right); else balance(node.left, node.key, node.value, removeLoop(k, node.right));
}
static function iteratorLoop<K,V>(node:TreeNode<K, V>, acc:Array<V>) {
if (node != null) {
iteratorLoop(node.left, acc);
acc.push(node.value);
iteratorLoop(node.right, acc);
}
}
function keysLoop(node:TreeNode<K, V>, acc:Array<K>) {
if (node != null) {
keysLoop(node.left, acc);
acc.push(node.key);
keysLoop(node.right, acc);
}
}
function merge(t1, t2) {
if (t1 == null)
return t2;
if (t2 == null)
return t1;
var t = minBinding(t2);
return balance(t1, t.key, t.value, removeMinBinding(t2));
}
function minBinding(t:TreeNode<K, V>) {
return if (t == null) throw "Not_found"; else if (t.left == null) t; else minBinding(t.left);
}
function removeMinBinding(t:TreeNode<K, V>) {
return if (t.left == null) t.right; else balance(removeMinBinding(t.left), t.key, t.value, t.right);
}
function balance(l:TreeNode<K, V>, k:K, v:V, r:TreeNode<K, V>):TreeNode<K, V> {
var hl = l.get_height();
var hr = r.get_height();
return if (hl > hr + 2) {
if (l.left.get_height() >= l.right.get_height())
new TreeNode<K, V>(l.left, l.key, l.value, new TreeNode<K, V>(l.right, k, v, r));
else
new TreeNode<K, V>(new TreeNode<K, V>(l.left, l.key, l.value, l.right.left), l.right.key, l.right.value,
new TreeNode<K, V>(l.right.right, k, v, r));
} else if (hr > hl + 2) {
if (r.right.get_height() > r.left.get_height())
new TreeNode<K, V>(new TreeNode<K, V>(l, k, v, r.left), r.key, r.value, r.right);
else
new TreeNode<K, V>(new TreeNode<K, V>(l, k, v, r.left.left), r.left.key, r.left.value,
new TreeNode<K, V>(r.left.right, r.key, r.value, r.right));
} else {
new TreeNode<K, V>(l, k, v, r, (hl > hr ? hl : hr) + 1);
}
}
function compare(k1:K, k2:K) {
return Reflect.compare(k1, k2);
}
public function toString() {
return root == null ? '{}' : '{${root.toString()}}';
}
/**
Removes all keys from `this` BalancedTree.
**/
public function clear():Void {
root = null;
}
}
/**
A tree node of `haxe.ds.BalancedTree`.
**/
class TreeNode<K, V> {
public var left:TreeNode<K, V>;
public var right:TreeNode<K, V>;
public var key:K;
public var value:V;
var _height:Int;
public function new(l, k, v, r, h = -1) {
left = l;
key = k;
value = v;
right = r;
if (h == -1)
_height = (left.get_height() > right.get_height() ? left.get_height() : right.get_height()) + 1;
else
_height = h;
}
extern public inline function get_height()
return this == null ? 0 : _height;
public function toString() {
return (left == null ? "" : left.toString() + ", ") + '$key=$value' + (right == null ? "" : ", " + right.toString());
}
}

View File

@ -0,0 +1,32 @@
/*
* 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 haxe.ds;
/**
Either represents values which are either of type `L` (Left) or type `R`
(Right).
**/
enum Either<L, R> {
Left(v:L);
Right(v:R);
}

View File

@ -0,0 +1,70 @@
/*
* 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 haxe.ds;
/**
EnumValueMap allows mapping of enum value keys to arbitrary values.
Keys are compared by value and recursively over their parameters. If any
parameter is not an enum value, `Reflect.compare` is used to compare them.
**/
class EnumValueMap<K:EnumValue, V> extends haxe.ds.BalancedTree<K, V> implements haxe.Constraints.IMap<K, V> {
override function compare(k1:EnumValue, k2:EnumValue):Int {
var d = k1.getIndex() - k2.getIndex();
if (d != 0)
return d;
var p1 = k1.getParameters();
var p2 = k2.getParameters();
if (p1.length == 0 && p2.length == 0)
return 0;
return compareArgs(p1, p2);
}
function compareArgs(a1:Array<Dynamic>, a2:Array<Dynamic>):Int {
var ld = a1.length - a2.length;
if (ld != 0)
return ld;
for (i in 0...a1.length) {
var d = compareArg(a1[i], a2[i]);
if (d != 0)
return d;
}
return 0;
}
function compareArg(v1:Dynamic, v2:Dynamic):Int {
return if (Reflect.isEnumValue(v1) && Reflect.isEnumValue(v2)) {
compare(v1, v2);
} else if (Std.isOfType(v1, Array) && Std.isOfType(v2, Array)) {
compareArgs(v1, v2);
} else {
Reflect.compare(v1, v2);
}
}
override function copy():EnumValueMap<K, V> {
var copied = new EnumValueMap<K, V>();
copied.root = root;
return copied;
}
}

View File

@ -0,0 +1,212 @@
/*
* 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 haxe.ds;
/**
A cell of `haxe.ds.GenericStack`.
@see https://haxe.org/manual/std-GenericStack.html
**/
#if (flash || cpp)
@:generic
#end
class GenericCell<T> {
public var elt:T;
public var next:GenericCell<T>;
public function new(elt, next) {
this.elt = elt;
this.next = next;
}
}
#if cpp
@:generic
#if cppia
private class GenericStackIterator<T> {
public var current:GenericCell<T>;
public function hasNext():Bool {
return current != null;
}
public function next():T {
var result = current.elt;
current = current.next;
return result;
}
public function new(head) {
current = head;
}
}
#else
private class GenericStackIterator<T> extends cpp.FastIterator<T> {
public var current:GenericCell<T>;
override public function hasNext():Bool {
return current != null;
}
override public function next():T {
var result = current.elt;
current = current.next;
return result;
}
public function new(head) {
current = head;
}
}
#end
#end
/**
A stack of elements.
This class is generic, which means one type is generated for each type
parameter T on static targets. For example:
- `new GenericStack<Int>()` generates `GenericStack_Int`
- `new GenericStack<String>()` generates `GenericStack_String`
The generated name is an implementation detail and should not be relied
upon.
@see https://haxe.org/manual/std-GenericStack.html
**/
#if (flash || cpp)
@:generic
#end
class GenericStack<T> {
public var head:GenericCell<T>;
/**
Creates a new empty GenericStack.
**/
public function new() {}
/**
Pushes element `item` onto the stack.
**/
public inline function add(item:T) {
head = new GenericCell<T>(item, head);
}
/**
Returns the topmost stack element without removing it.
If the stack is empty, null is returned.
**/
public inline function first():Null<T> {
return if (head == null) null else head.elt;
}
/**
Returns the topmost stack element and removes it.
If the stack is empty, null is returned.
**/
public inline function pop():Null<T> {
var k = head;
if (k == null)
return null;
else {
head = k.next;
return k.elt;
}
}
/**
Tells if the stack is empty.
**/
public inline function isEmpty():Bool {
return (head == null);
}
/**
Removes the first element which is equal to `v` according to the `==`
operator.
This method traverses the stack until it finds a matching element and
unlinks it, returning true.
If no matching element is found, false is returned.
**/
public function remove(v:T):Bool {
var prev:GenericCell<T> = null;
var l = head;
while (l != null) {
if (l.elt == v) {
if (prev == null)
head = l.next;
else
prev.next = l.next;
break;
}
prev = l;
l = l.next;
}
return (l != null);
}
#if cpp
/**
Returns an iterator over the elements of `this` GenericStack.
**/
public function iterator():Iterator<T> {
return new GenericStackIterator<T>(head);
}
#else
/**
Returns an iterator over the elements of `this` GenericStack.
**/
public function iterator():Iterator<T> {
var l = head;
return {
hasNext: function() {
return l != null;
},
next: function() {
var k = l;
l = k.next;
return k.elt;
}
};
}
#end
/**
Returns a String representation of `this` GenericStack.
**/
public function toString() {
var a = new Array();
var l = head;
while (l != null) {
a.push(l.elt);
l = l.next;
}
return "{" + a.join(",") + "}";
}
}

View File

@ -0,0 +1,120 @@
/*
* 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 haxe.ds;
import haxe.iterators.HashMapKeyValueIterator;
/**
HashMap allows mapping of hashable objects to arbitrary values.
See `Map` for documentation details.
@see https://haxe.org/manual/std-Map.html
**/
abstract HashMap<K:{function hashCode():Int;}, V>(HashMapData<K, V>) {
/**
Creates a new HashMap.
**/
public inline function new() {
this = new HashMapData();
}
/**
See `Map.set`
**/
@:arrayAccess public inline function set(k:K, v:V) {
this.keys.set(k.hashCode(), k);
this.values.set(k.hashCode(), v);
}
/**
See `Map.get`
**/
@:arrayAccess public inline function get(k:K) {
return this.values.get(k.hashCode());
}
/**
See `Map.exists`
**/
public inline function exists(k:K) {
return this.values.exists(k.hashCode());
}
/**
See `Map.remove`
**/
public inline function remove(k:K) {
this.values.remove(k.hashCode());
return this.keys.remove(k.hashCode());
}
/**
See `Map.keys`
**/
public inline function keys() {
return this.keys.iterator();
}
/**
See `Map.copy`
**/
public function copy():HashMap<K, V> {
var copied = new HashMapData();
copied.keys = this.keys.copy();
copied.values = this.values.copy();
return cast copied;
}
/**
See `Map.iterator`
**/
public inline function iterator() {
return this.values.iterator();
}
/**
See `Map.keyValueIterator`
**/
public inline function keyValueIterator():HashMapKeyValueIterator<K, V> {
return new HashMapKeyValueIterator(cast this);
}
/**
See `Map.clear`
**/
public inline function clear():Void {
this.keys.clear();
this.values.clear();
}
}
private class HashMapData<K:{function hashCode():Int;}, V> {
public var keys:IntMap<K>;
public var values:IntMap<V>;
public inline function new() {
keys = new IntMap();
values = new IntMap();
}
}

View File

@ -0,0 +1,99 @@
/*
* 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 haxe.ds;
/**
IntMap allows mapping of Int keys to arbitrary values.
See `Map` for documentation details.
@see https://haxe.org/manual/std-Map.html
**/
extern class IntMap<T> implements haxe.Constraints.IMap<Int, T> {
/**
Creates a new IntMap.
**/
function new():Void;
/**
See `Map.set`
**/
function set(key:Int, value:T):Void;
/**
See `Map.get`
**/
function get(key:Int):Null<T>;
/**
See `Map.exists`
**/
function exists(key:Int):Bool;
/**
See `Map.remove`
**/
function remove(key:Int):Bool;
/**
See `Map.keys`
(cs, java) Implementation detail: Do not `set()` any new value while
iterating, as it may cause a resize, which will break iteration.
**/
function keys():Iterator<Int>;
/**
See `Map.iterator`
(cs, java) Implementation detail: Do not `set()` any new value while
iterating, as it may cause a resize, which will break iteration.
**/
function iterator():Iterator<T>;
/**
See `Map.keyValueIterator`
**/
#if eval
@:runtime inline function keyValueIterator():KeyValueIterator<Int, T> {
return new haxe.iterators.MapKeyValueIterator(this);
}
#else
function keyValueIterator():KeyValueIterator<Int, T>;
#end
/**
See `Map.copy`
**/
function copy():IntMap<T>;
/**
See `Map.toString`
**/
function toString():String;
/**
See `Map.clear`
**/
function clear():Void;
}

View File

@ -0,0 +1,313 @@
/*
* 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 haxe.ds;
/**
A linked-list of elements. The list is composed of element container objects
that are chained together. It is optimized so that adding or removing an
element does not imply copying the whole list content every time.
@see https://haxe.org/manual/std-List.html
**/
class List<T> {
private var h:ListNode<T>;
private var q:ListNode<T>;
/**
The length of `this` List.
**/
public var length(default, null):Int;
/**
Creates a new empty list.
**/
public function new() {
length = 0;
}
/**
Adds element `item` at the end of `this` List.
`this.length` increases by 1.
**/
public function add(item:T) {
var x = ListNode.create(item, null);
if (h == null)
h = x;
else
q.next = x;
q = x;
length++;
}
/**
Adds element `item` at the beginning of `this` List.
`this.length` increases by 1.
**/
public function push(item:T) {
var x = ListNode.create(item, h);
h = x;
if (q == null)
q = x;
length++;
}
/**
Returns the first element of `this` List, or null if no elements exist.
This function does not modify `this` List.
**/
public function first():Null<T> {
return if (h == null) null else h.item;
}
/**
Returns the last element of `this` List, or null if no elements exist.
This function does not modify `this` List.
**/
public function last():Null<T> {
return if (q == null) null else q.item;
}
/**
Returns the first element of `this` List, or null if no elements exist.
The element is removed from `this` List.
**/
public function pop():Null<T> {
if (h == null)
return null;
var x = h.item;
h = h.next;
if (h == null)
q = null;
length--;
return x;
}
/**
Tells if `this` List is empty.
**/
public function isEmpty():Bool {
return (h == null);
}
/**
Empties `this` List.
This function does not traverse the elements, but simply sets the
internal references to null and `this.length` to 0.
**/
public function clear():Void {
h = null;
q = null;
length = 0;
}
/**
Removes the first occurrence of `v` in `this` List.
If `v` is found by checking standard equality, it is removed from `this`
List and the function returns true.
Otherwise, false is returned.
**/
public function remove(v:T):Bool {
var prev:ListNode<T> = null;
var l = h;
while (l != null) {
if (l.item == v) {
if (prev == null)
h = l.next;
else
prev.next = l.next;
if (q == l)
q = prev;
length--;
return true;
}
prev = l;
l = l.next;
}
return false;
}
/**
Returns an iterator on the elements of the list.
**/
public inline function iterator():ListIterator<T> {
return new ListIterator<T>(h);
}
/**
Returns an iterator of the List indices and values.
**/
@:pure @:runtime public inline function keyValueIterator():ListKeyValueIterator<T> {
return new ListKeyValueIterator(h);
}
/**
Returns a string representation of `this` List.
The result is enclosed in { } with the individual elements being
separated by a comma.
**/
public function toString() {
var s = new StringBuf();
var first = true;
var l = h;
s.add("{");
while (l != null) {
if (first)
first = false;
else
s.add(", ");
s.add(Std.string(l.item));
l = l.next;
}
s.add("}");
return s.toString();
}
/**
Returns a string representation of `this` List, with `sep` separating
each element.
**/
public function join(sep:String) {
var s = new StringBuf();
var first = true;
var l = h;
while (l != null) {
if (first)
first = false;
else
s.add(sep);
s.add(l.item);
l = l.next;
}
return s.toString();
}
/**
Returns a list filtered with `f`. The returned list will contain all
elements for which `f(x) == true`.
**/
public function filter(f:T->Bool) {
var l2 = new List();
var l = h;
while (l != null) {
var v = l.item;
l = l.next;
if (f(v))
l2.add(v);
}
return l2;
}
/**
Returns a new list where all elements have been converted by the
function `f`.
**/
public function map<X>(f:T->X):List<X> {
var b = new List();
var l = h;
while (l != null) {
var v = l.item;
l = l.next;
b.add(f(v));
}
return b;
}
}
#if neko
private extern class ListNode<T> extends neko.NativeArray<Dynamic> {
var item(get, set):T;
var next(get, set):ListNode<T>;
private inline function get_item():T
return this[0];
private inline function set_item(v:T):T
return this[0] = v;
private inline function get_next():ListNode<T>
return this[1];
private inline function set_next(v:ListNode<T>):ListNode<T>
return this[1] = v;
inline static function create<T>(item:T, next:ListNode<T>):ListNode<T> {
return untyped __dollar__array(item, next);
}
}
#else
private class ListNode<T> {
public var item:T;
public var next:ListNode<T>;
public function new(item:T, next:ListNode<T>) {
this.item = item;
this.next = next;
}
extern public inline static function create<T>(item:T, next:ListNode<T>):ListNode<T> {
return new ListNode(item, next);
}
}
#end
private class ListIterator<T> {
var head:ListNode<T>;
public inline function new(head:ListNode<T>) {
this.head = head;
}
public inline function hasNext():Bool {
return head != null;
}
public inline function next():T {
var val = head.item;
head = head.next;
return val;
}
}
private class ListKeyValueIterator<T> {
var idx:Int;
var head:ListNode<T>;
public inline function new(head:ListNode<T>) {
this.head = head;
this.idx = 0;
}
public inline function hasNext():Bool {
return head != null;
}
public inline function next():{key:Int, value:T} {
var val = head.item;
head = head.next;
return {value: val, key: idx++};
}
}

View File

@ -0,0 +1,149 @@
/*
* 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 haxe.ds;
/**
ListSort provides a stable implementation of merge sort through its `sort`
method. It has a O(N.log(N)) complexity and does not require additional memory allocation.
**/
class ListSort {
// Note : we prefer [inline] over [@:generic] here since we want to inline the comparison function as well
/**
Sorts List `lst` according to the comparison function `cmp`, where
`cmp(x,y)` returns 0 if `x == y`, a positive Int if `x > y` and a
negative Int if `x < y`.
This operation modifies List `a` in place and returns its head once modified.
The `prev` of the head is set to the tail of the sorted list.
If `list` or `cmp` are null, the result is unspecified.
**/
public static inline function sort<T:{prev:T, next:T}>(list:T, cmp:T->T->Int):T {
// ported from http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
if (list == null)
return null;
var insize = 1, nmerges, psize = 0, qsize = 0;
var p, q, e, tail:T = null;
while (true) {
p = list;
list = null;
tail = null;
nmerges = 0;
while (p != null) {
nmerges++;
q = p;
psize = 0;
for (i in 0...insize) {
psize++;
q = q.next;
if (q == null)
break;
}
qsize = insize;
while (psize > 0 || (qsize > 0 && q != null)) {
if (psize == 0) {
e = q;
q = q.next;
qsize--;
} else if (qsize == 0 || q == null || cmp(p, q) <= 0) {
e = p;
p = p.next;
psize--;
} else {
e = q;
q = q.next;
qsize--;
}
if (tail != null)
tail.next = e;
else
list = e;
e.prev = tail;
tail = e;
}
p = q;
}
tail.next = null;
if (nmerges <= 1)
break;
insize *= 2;
}
list.prev = tail;
return list;
}
/**
Same as `sort` but on single linked list.
**/
public static inline function sortSingleLinked<T:{next:T}>(list:T, cmp:T->T->Int):T {
if (list == null)
return null;
var insize = 1, nmerges, psize = 0, qsize = 0;
var p, q, e, tail:T;
while (true) {
p = list;
list = null;
tail = null;
nmerges = 0;
while (p != null) {
nmerges++;
q = p;
psize = 0;
for (i in 0...insize) {
psize++;
q = q.next;
if (q == null)
break;
}
qsize = insize;
while (psize > 0 || (qsize > 0 && q != null)) {
if (psize == 0) {
e = q;
q = q.next;
qsize--;
} else if (qsize == 0 || q == null || cmp(p, q) <= 0) {
e = p;
p = p.next;
psize--;
} else {
e = q;
q = q.next;
qsize--;
}
if (tail != null)
tail.next = e;
else
list = e;
tail = e;
}
p = q;
}
tail.next = null;
if (nmerges <= 1)
break;
insize *= 2;
}
return list;
}
}

View File

@ -0,0 +1,197 @@
/*
* 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 haxe.ds;
import haxe.ds.StringMap;
import haxe.ds.IntMap;
import haxe.ds.HashMap;
import haxe.ds.ObjectMap;
import haxe.ds.WeakMap;
import haxe.ds.EnumValueMap;
import haxe.Constraints.IMap;
/**
Map allows key to value mapping for arbitrary value types, and many key
types.
This is a multi-type abstract, it is instantiated as one of its
specialization types depending on its type parameters.
A Map can be instantiated without explicit type parameters. Type inference
will then determine the type parameters from the usage.
Maps can also be created with `[key1 => value1, key2 => value2]` syntax.
Map is an abstract type, it is not available at runtime.
@see https://haxe.org/manual/std-Map.html
**/
@:transitive
@:multiType(@:followWithAbstracts K)
abstract Map<K, V>(IMap<K, V>) {
/**
Creates a new Map.
This becomes a constructor call to one of the specialization types in
the output. The rules for that are as follows:
1. if `K` is a `String`, `haxe.ds.StringMap` is used
2. if `K` is an `Int`, `haxe.ds.IntMap` is used
3. if `K` is an `EnumValue`, `haxe.ds.EnumValueMap` is used
4. if `K` is any other class or structure, `haxe.ds.ObjectMap` is used
5. if `K` is any other type, it causes a compile-time error
(Cpp) Map does not use weak keys on `ObjectMap` by default.
**/
public function new();
/**
Maps `key` to `value`.
If `key` already has a mapping, the previous value disappears.
If `key` is `null`, the result is unspecified.
**/
public inline function set(key:K, value:V)
this.set(key, value);
/**
Returns the current mapping of `key`.
If no such mapping exists, `null` is returned.
Note that a check like `map.get(key) == null` can hold for two reasons:
1. the map has no mapping for `key`
2. the map has a mapping with a value of `null`
If it is important to distinguish these cases, `exists()` should be
used.
If `key` is `null`, the result is unspecified.
**/
@:arrayAccess public inline function get(key:K)
return this.get(key);
/**
Returns true if `key` has a mapping, false otherwise.
If `key` is `null`, the result is unspecified.
**/
public inline function exists(key:K)
return this.exists(key);
/**
Removes the mapping of `key` and returns true if such a mapping existed,
false otherwise.
If `key` is `null`, the result is unspecified.
**/
public inline function remove(key:K)
return this.remove(key);
/**
Returns an Iterator over the keys of `this` Map.
The order of keys is undefined.
**/
public inline function keys():Iterator<K> {
return this.keys();
}
/**
Returns an Iterator over the values of `this` Map.
The order of values is undefined.
**/
public inline function iterator():Iterator<V> {
return this.iterator();
}
/**
Returns an Iterator over the keys and values of `this` Map.
The order of values is undefined.
**/
public inline function keyValueIterator():KeyValueIterator<K, V> {
return this.keyValueIterator();
}
/**
Returns a shallow copy of `this` map.
The order of values is undefined.
**/
public inline function copy():Map<K, V> {
return cast this.copy();
}
/**
Returns a String representation of `this` Map.
The exact representation depends on the platform and key-type.
**/
public inline function toString():String {
return this.toString();
}
/**
Removes all keys from `this` Map.
**/
public inline function clear():Void {
this.clear();
}
@:arrayAccess @:noCompletion public inline function arrayWrite(k:K, v:V):V {
this.set(k, v);
return v;
}
@:to static inline function toStringMap<K:String, V>(t:IMap<K, V>):StringMap<V> {
return new StringMap<V>();
}
@:to static inline function toIntMap<K:Int, V>(t:IMap<K, V>):IntMap<V> {
return new IntMap<V>();
}
@:to static inline function toEnumValueMapMap<K:EnumValue, V>(t:IMap<K, V>):EnumValueMap<K, V> {
return new EnumValueMap<K, V>();
}
@:to static inline function toObjectMap<K:{}, V>(t:IMap<K, V>):ObjectMap<K, V> {
return new ObjectMap<K, V>();
}
@:from static inline function fromStringMap<V>(map:StringMap<V>):Map<String, V> {
return cast map;
}
@:from static inline function fromIntMap<V>(map:IntMap<V>):Map<Int, V> {
return cast map;
}
@:from static inline function fromObjectMap<K:{}, V>(map:ObjectMap<K, V>):Map<K, V> {
return cast map;
}
}

View File

@ -0,0 +1,102 @@
/*
* 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 haxe.ds;
/**
ObjectMap allows mapping of object keys to arbitrary values.
On static targets, the keys are considered to be strong references. Refer
to `haxe.ds.WeakMap` for a weak reference version.
See `Map` for documentation details.
@see https://haxe.org/manual/std-Map.html
**/
extern class ObjectMap<K:{}, V> implements haxe.Constraints.IMap<K, V> {
/**
Creates a new ObjectMap.
**/
function new():Void;
/**
See `Map.set`
**/
function set(key:K, value:V):Void;
/**
See `Map.get`
**/
function get(key:K):Null<V>;
/**
See `Map.exists`
**/
function exists(key:K):Bool;
/**
See `Map.remove`
**/
function remove(key:K):Bool;
/**
See `Map.keys`
(cs, java) Implementation detail: Do not `set()` any new value while
iterating, as it may cause a resize, which will break iteration.
**/
function keys():Iterator<K>;
/**
See `Map.iterator`
(cs, java) Implementation detail: Do not `set()` any new value while
iterating, as it may cause a resize, which will break iteration.
**/
function iterator():Iterator<V>;
/**
See `Map.keyValueIterator`
**/
#if eval
@:runtime inline function keyValueIterator():KeyValueIterator<K, V> {
return new haxe.iterators.MapKeyValueIterator(this);
}
#else
function keyValueIterator():KeyValueIterator<K, V>;
#end
/**
See `Map.copy`
**/
function copy():ObjectMap<K, V>;
/**
See `Map.toString`
**/
function toString():String;
/**
See `Map.clear`
**/
function clear():Void;
}

View File

@ -0,0 +1,34 @@
/*
* 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 haxe.ds;
/**
An Option is a wrapper type which can either have a value (Some) or not a
value (None).
@see https://haxe.org/manual/std-Option.html
**/
enum Option<T> {
Some(v:T);
None;
}

View File

@ -0,0 +1,62 @@
/*
* 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 haxe.ds;
/**
`ReadOnlyArray` is an abstract over an ordinary `Array` which only exposes
APIs that don't modify the instance, hence "read-only".
Note that this doesn't necessarily mean that the instance is *immutable*.
Other code holding a reference to the underlying `Array` can still modify it,
and the reference can be obtained with a `cast`.
**/
@:forward(copy, filter, indexOf, iterator, keyValueIterator, join, lastIndexOf, map, slice, contains, toString)
abstract ReadOnlyArray<T>(Array<T>) from Array<T> to Iterable<T> {
/**
The length of `this` Array.
**/
public var length(get, never):Int;
inline function get_length()
return this.length;
@:arrayAccess inline function get(i:Int)
return this[i];
/**
Returns a new Array by appending the elements of `a` to the elements of
`this` Array.
This operation does not modify `this` Array.
If `a` is the empty Array `[]`, a copy of `this` Array is returned.
The length of the returned Array is equal to the sum of `this.length`
and `a.length`.
If `a` is `null`, the result is unspecified.
**/
public inline function concat(a:ReadOnlyArray<T>):Array<T> {
return this.concat(cast a);
}
}

View File

@ -0,0 +1,99 @@
/*
* 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 haxe.ds;
/**
StringMap allows mapping of String keys to arbitrary values.
See `Map` for documentation details.
@see https://haxe.org/manual/std-Map.html
**/
extern class StringMap<T> implements haxe.Constraints.IMap<String, T> {
/**
Creates a new StringMap.
**/
function new():Void;
/**
See `Map.set`
**/
function set(key:String, value:T):Void;
/**
See `Map.get`
**/
function get(key:String):Null<T>;
/**
See `Map.exists`
**/
function exists(key:String):Bool;
/**
See `Map.remove`
**/
function remove(key:String):Bool;
/**
See `Map.keys`
(cs, java) Implementation detail: Do not `set()` any new value while
iterating, as it may cause a resize, which will break iteration.
**/
function keys():Iterator<String>;
/**
See `Map.iterator`
(cs, java) Implementation detail: Do not `set()` any new value while
iterating, as it may cause a resize, which will break iteration.
**/
function iterator():Iterator<T>;
/**
See `Map.keyValueIterator`
**/
#if eval
@:runtime inline function keyValueIterator():KeyValueIterator<String, T> {
return new haxe.iterators.MapKeyValueIterator(this);
}
#else
function keyValueIterator():KeyValueIterator<String, T>;
#end
/**
See `Map.copy`
**/
function copy():StringMap<T>;
/**
See `Map.toString`
**/
function toString():String;
/**
See `Map.clear`
**/
function clear():Void;
}

View File

@ -0,0 +1,357 @@
/*
* 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 haxe.ds;
#if cpp
using cpp.NativeArray;
#end
private typedef VectorData<T> =
#if flash10
flash.Vector<T>
#elseif neko
neko.NativeArray<T>
#elseif cs
cs.NativeArray<T>
#elseif java
java.NativeArray<T>
#elseif lua
lua.Table<Int, T>
#elseif eval
eval.Vector<T>
#else
Array<T>
#end
/**
A Vector is a storage of fixed size. It can be faster than Array on some
targets, and is never slower.
@see https://haxe.org/manual/std-vector.html
**/
abstract Vector<T>(VectorData<T>) {
/**
Creates a new Vector of length `length`.
Initially `this` Vector contains `length` neutral elements:
- always null on dynamic targets
- 0, 0.0 or false for Int, Float and Bool respectively on static targets
- null for other types on static targets
If `length` is less than or equal to 0, the result is unspecified.
**/
public inline function new(length:Int) {
#if flash10
this = new flash.Vector<T>(length, true);
#elseif neko
this = untyped __dollar__amake(length);
#elseif js
this = js.Syntax.construct(Array, length);
#elseif cs
this = new cs.NativeArray(length);
#elseif java
this = new java.NativeArray(length);
#elseif cpp
this = NativeArray.create(length);
#elseif python
this = python.Syntax.code("[{0}]*{1}", null, length);
#elseif lua
this = untyped __lua_table__({length: length});
#elseif eval
this = new eval.Vector(length);
#else
this = [];
untyped this.length = length;
#end
}
/**
Returns the value at index `index`.
If `index` is negative or exceeds `this.length`, the result is
unspecified.
**/
@:op([]) public inline function get(index:Int):T {
#if cpp
return this.unsafeGet(index);
#elseif python
return python.internal.ArrayImpl.unsafeGet(this, index);
#elseif eval
return this[index];
#else
return this[index];
#end
}
/**
Sets the value at index `index` to `val`.
If `index` is negative or exceeds `this.length`, the result is
unspecified.
**/
@:op([]) public inline function set(index:Int, val:T):T {
#if cpp
return this.unsafeSet(index, val);
#elseif python
return python.internal.ArrayImpl.unsafeSet(this, index, val);
#elseif eval
return this[index] = val;
#else
return this[index] = val;
#end
}
/**
Returns the length of `this` Vector.
**/
public var length(get, never):Int;
inline function get_length():Int {
#if neko
return untyped __dollar__asize(this);
#elseif cs
return this.Length;
#elseif java
return this.length;
#elseif python
return this.length;
#else
return untyped this.length;
#end
}
/**
Copies `length` of elements from `src` Vector, beginning at `srcPos` to
`dest` Vector, beginning at `destPos`
The results are unspecified if `length` results in out-of-bounds access,
or if `src` or `dest` are null
**/
public static #if (cs || java || neko || cpp || eval) inline #end function blit<T>(src:Vector<T>, srcPos:Int, dest:Vector<T>, destPos:Int, len:Int):Void {
#if neko
untyped __dollar__ablit(dest, destPos, src, srcPos, len);
#elseif java
java.lang.System.arraycopy(src, srcPos, dest, destPos, len);
#elseif cs
cs.system.Array.Copy(cast src, srcPos, cast dest, destPos, len);
#elseif cpp
dest.toData().blit(destPos, src.toData(), srcPos, len);
#elseif eval
src.toData().blit(srcPos, dest.toData(), destPos, len);
#else
if (src == dest) {
if (srcPos < destPos) {
var i = srcPos + len;
var j = destPos + len;
for (k in 0...len) {
i--;
j--;
src[j] = src[i];
}
} else if (srcPos > destPos) {
var i = srcPos;
var j = destPos;
for (k in 0...len) {
src[j] = src[i];
i++;
j++;
}
}
} else {
for (i in 0...len) {
dest[destPos + i] = src[srcPos + i];
}
}
#end
}
/**
Creates a new Array, copy the content from the Vector to it, and returns it.
**/
public #if (flash || cpp || js || java || eval) inline #end function toArray():Array<T> {
#if cpp
return this.copy();
#elseif python
return this.copy();
#elseif js
return this.slice(0);
#elseif eval
return this.toArray();
#else
var a = new Array();
var len = length;
#if (neko)
// prealloc good size
if (len > 0)
a[len - 1] = get(0);
#end
for (i in 0...len)
a[i] = get(i);
return a;
#end
}
/**
Extracts the data of `this` Vector.
This returns the internal representation type.
**/
public inline function toData():VectorData<T>
return cast this;
/**
Initializes a new Vector from `data`.
Since `data` is the internal representation of Vector, this is a no-op.
If `data` is null, the corresponding Vector is also `null`.
**/
static public inline function fromData<T>(data:VectorData<T>):Vector<T>
return cast data;
/**
Creates a new Vector by copying the elements of `array`.
This always creates a copy, even on platforms where the internal
representation is Array.
The elements are not copied and retain their identity, so
`a[i] == Vector.fromArrayCopy(a).get(i)` is true for any valid i.
If `array` is null, the result is unspecified.
**/
static public inline function fromArrayCopy<T>(array:Array<T>):Vector<T> {
#if python
return cast array.copy();
#elseif flash10
return fromData(flash.Vector.ofArray(array));
#elseif java
return fromData(java.Lib.nativeArray(array, false));
#elseif cs
return fromData(cs.Lib.nativeArray(array, false));
#elseif cpp
return cast array.copy();
#elseif js
return fromData(array.slice(0));
#elseif eval
return fromData(eval.Vector.fromArrayCopy(array));
#else
// TODO: Optimize this for others?
var vec = new Vector<T>(array.length);
for (i in 0...array.length)
vec.set(i, array[i]);
return vec;
#end
}
/**
Returns a shallow copy of `this` Vector.
The elements are not copied and retain their identity, so
`a[i] == a.copy()[i]` is true for any valid `i`. However,
`a == a.copy()` is always false.
**/
#if cs extern #end public inline function copy<T>():Vector<T> {
#if eval
return fromData(this.copy());
#else
var r = new Vector<T>(length);
Vector.blit(cast this, 0, r, 0, length);
return r;
#end
}
/**
Returns a string representation of `this` Vector, with `sep` separating
each element.
The result of this operation is equal to `Std.string(this[0]) + sep +
Std.string(this[1]) + sep + ... + sep + Std.string(this[this.length-1])`
If `this` Vector has length 0, the result is the empty String `""`.
If `this` has exactly one element, the result is equal to a call to
`Std.string(this[0])`.
If `sep` is null, the result is unspecified.
**/
#if cs extern #end public inline function join<T>(sep:String):String {
#if (flash10 || cpp || eval)
return this.join(sep);
#else
var b = new StringBuf();
var len = length;
for (i in 0...len) {
b.add(Std.string(get(i)));
if (i < len - 1) {
b.add(sep);
}
}
return b.toString();
#end
}
/**
Creates a new Vector by applying function `f` to all elements of `this`.
The order of elements is preserved.
If `f` is null, the result is unspecified.
**/
#if cs extern #end public inline function map<S>(f:T->S):Vector<S> {
#if eval
return fromData(this.map(f));
#else
var length = length;
var r = new Vector<S>(length);
var len = length;
for (i in 0...len) {
var v = f(get(i));
r.set(i, v);
}
return r;
#end
}
/**
Sorts `this` Vector according to the comparison function `f`, where
`f(x,y)` returns 0 if x == y, a positive Int if x > y and a
negative Int if x < y.
This operation modifies `this` Vector in place.
The sort operation is not guaranteed to be stable, which means that the
order of equal elements may not be retained.
If `f` is null, the result is unspecified.
**/
public inline function sort(f:T->T->Int):Void {
#if (neko || cs || java || eval)
throw "not yet supported";
#elseif lua
haxe.ds.ArraySort.sort(cast this, f);
#else
this.sort(f);
#end
}
}

View File

@ -0,0 +1,107 @@
/*
* 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 haxe.ds;
/**
WeakMap allows mapping of object keys to arbitrary values.
The keys are considered to be weak references on static targets.
See `Map` for documentation details.
@see https://haxe.org/manual/std-Map.html
**/
class WeakMap<K:{}, V> implements haxe.Constraints.IMap<K, V> {
/**
Creates a new WeakMap.
**/
public function new():Void {
throw new haxe.exceptions.NotImplementedException("Not implemented for this platform");
}
/**
See `Map.set`
**/
public function set(key:K, value:V):Void {}
/**
See `Map.get`
**/
public function get(key:K):Null<V> {
return null;
}
/**
See `Map.exists`
**/
public function exists(key:K):Bool {
return false;
}
/**
See `Map.remove`
**/
public function remove(key:K):Bool {
return false;
}
/**
See `Map.keys`
**/
public function keys():Iterator<K> {
return null;
}
/**
See `Map.iterator`
**/
public function iterator():Iterator<V> {
return null;
}
/**
See `Map.keyValueIterator`
**/
public inline function keyValueIterator():KeyValueIterator<K, V> {
return null;
}
/**
See `Map.copy`
**/
public function copy():WeakMap<K, V> {
return null;
}
/**
See `Map.toString`
**/
public function toString():String {
return null;
}
/**
See `Map.clear`
**/
public function clear():Void {}
}

View File

@ -0,0 +1,16 @@
package haxe.exceptions;
/**
An exception that is thrown when an invalid value provided for an argument of a function.
**/
class ArgumentException extends PosException {
/**
An argument name.
**/
public final argument:String;
public function new(argument:String, ?message:String, ?previous:Exception, ?pos:PosInfos):Void {
super(message == null ? 'Invalid argument "$argument"' : message, previous, pos);
this.argument = argument;
}
}

View File

@ -0,0 +1,10 @@
package haxe.exceptions;
/**
An exception that is thrown when requested function or operation does not have an implementation.
**/
class NotImplementedException extends PosException {
public function new(message:String = 'Not implemented', ?previous:Exception, ?pos:PosInfos):Void {
super(message, previous, pos);
}
}

View File

@ -0,0 +1,27 @@
package haxe.exceptions;
/**
An exception that carry position information of a place where it was created.
**/
class PosException extends Exception {
/**
Position where this exception was created.
**/
public final posInfos:PosInfos;
public function new(message:String, ?previous:Exception, ?pos:PosInfos):Void {
super(message, previous);
if (pos == null) {
posInfos = { fileName:'(unknown)', lineNumber:0, className:'(unknown)', methodName:'(unknown)' }
} else {
posInfos = pos;
}
}
/**
Returns exception message.
**/
override function toString():String {
return '${super.toString()} in ${posInfos.className}.${posInfos.methodName} at ${posInfos.fileName}:${posInfos.lineNumber}';
}
}

View File

@ -0,0 +1,32 @@
/*
* 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 haxe.extern;
/**
If this type is used as an argument type, the compiler ensures that
argument expressions are bound to a local variable.
**/
@:forward
@:transitive
@:semantics(variable)
abstract AsVar<T>(T) from T to T {}

View File

@ -0,0 +1,37 @@
/*
* 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 haxe.extern;
/**
An abstract type allowing values to be either of `T1` or `T2` type.
Supports implicit casts from/to either types.
It is useful for interfacing with external code on dynamic platforms
such as JavaScript or Python.
Otherwise, use of this type is discouraged.
@see <https://haxe.org/manual/lf-externs.html>
**/
@:transitive
abstract EitherType<T1, T2>(Dynamic) from T1 to T1 from T2 to T2 {}

34
Kha/Tools/macos/std/haxe/extern/Rest.hx vendored Normal file
View File

@ -0,0 +1,34 @@
/*
* 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 haxe.extern;
/**
DEPRECATED: use haxe.Rest instead.
A special type that represents "rest" function argument.
Should be used as a type for the last argument of an extern method,
representing that arbitrary number of arguments of given type can be
passed to that method.
@see <https://haxe.org/manual/lf-externs.html>
**/
typedef Rest<T> = haxe.Rest<T>

View File

@ -0,0 +1,324 @@
/*
* 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 haxe.format;
/**
An implementation of JSON parser in Haxe.
This class is used by `haxe.Json` when native JSON implementation
is not available.
@see https://haxe.org/manual/std-Json-parsing.html
**/
class JsonParser {
/**
Parses given JSON-encoded `str` and returns the resulting object.
JSON objects are parsed into anonymous structures and JSON arrays
are parsed into `Array<Dynamic>`.
If given `str` is not valid JSON, an exception will be thrown.
If `str` is null, the result is unspecified.
**/
static public inline function parse(str:String):Dynamic {
return new JsonParser(str).doParse();
}
var str:String;
var pos:Int;
function new(str:String) {
this.str = str;
this.pos = 0;
}
function doParse():Dynamic {
var result = parseRec();
var c;
while (!StringTools.isEof(c = nextChar())) {
switch (c) {
case ' '.code, '\r'.code, '\n'.code, '\t'.code:
// allow trailing whitespace
default:
invalidChar();
}
}
return result;
}
function parseRec():Dynamic {
while (true) {
var c = nextChar();
switch (c) {
case ' '.code, '\r'.code, '\n'.code, '\t'.code:
// loop
case '{'.code:
var obj = {}, field = null, comma:Null<Bool> = null;
while (true) {
var c = nextChar();
switch (c) {
case ' '.code, '\r'.code, '\n'.code, '\t'.code:
// loop
case '}'.code:
if (field != null || comma == false)
invalidChar();
return obj;
case ':'.code:
if (field == null)
invalidChar();
Reflect.setField(obj, field, parseRec());
field = null;
comma = true;
case ','.code:
if (comma) comma = false else invalidChar();
case '"'.code:
if (field != null || comma) invalidChar();
field = parseString();
default:
invalidChar();
}
}
case '['.code:
var arr = [], comma:Null<Bool> = null;
while (true) {
var c = nextChar();
switch (c) {
case ' '.code, '\r'.code, '\n'.code, '\t'.code:
// loop
case ']'.code:
if (comma == false) invalidChar();
return arr;
case ','.code:
if (comma) comma = false else invalidChar();
default:
if (comma) invalidChar();
pos--;
arr.push(parseRec());
comma = true;
}
}
case 't'.code:
var save = pos;
if (nextChar() != 'r'.code || nextChar() != 'u'.code || nextChar() != 'e'.code) {
pos = save;
invalidChar();
}
return true;
case 'f'.code:
var save = pos;
if (nextChar() != 'a'.code || nextChar() != 'l'.code || nextChar() != 's'.code || nextChar() != 'e'.code) {
pos = save;
invalidChar();
}
return false;
case 'n'.code:
var save = pos;
if (nextChar() != 'u'.code || nextChar() != 'l'.code || nextChar() != 'l'.code) {
pos = save;
invalidChar();
}
return null;
case '"'.code:
return parseString();
case '0'.code, '1'.code, '2'.code, '3'.code, '4'.code, '5'.code, '6'.code, '7'.code, '8'.code, '9'.code, '-'.code:
return parseNumber(c);
default:
invalidChar();
}
}
}
function parseString() {
var start = pos;
var buf:StringBuf = null;
#if target.unicode
var prev = -1;
inline function cancelSurrogate() {
// invalid high surrogate (not followed by low surrogate)
buf.addChar(0xFFFD);
prev = -1;
}
#end
while (true) {
var c = nextChar();
if (c == '"'.code)
break;
if (c == '\\'.code) {
if (buf == null) {
buf = new StringBuf();
}
buf.addSub(str, start, pos - start - 1);
c = nextChar();
#if target.unicode
if (c != "u".code && prev != -1)
cancelSurrogate();
#end
switch (c) {
case "r".code:
buf.addChar("\r".code);
case "n".code:
buf.addChar("\n".code);
case "t".code:
buf.addChar("\t".code);
case "b".code:
buf.addChar(8);
case "f".code:
buf.addChar(12);
case "/".code, '\\'.code, '"'.code:
buf.addChar(c);
case 'u'.code:
var uc:Int = Std.parseInt("0x" + str.substr(pos, 4));
pos += 4;
#if !target.unicode
if (uc <= 0x7F)
buf.addChar(uc);
else if (uc <= 0x7FF) {
buf.addChar(0xC0 | (uc >> 6));
buf.addChar(0x80 | (uc & 63));
} else if (uc <= 0xFFFF) {
buf.addChar(0xE0 | (uc >> 12));
buf.addChar(0x80 | ((uc >> 6) & 63));
buf.addChar(0x80 | (uc & 63));
} else {
buf.addChar(0xF0 | (uc >> 18));
buf.addChar(0x80 | ((uc >> 12) & 63));
buf.addChar(0x80 | ((uc >> 6) & 63));
buf.addChar(0x80 | (uc & 63));
}
#else
if (prev != -1) {
if (uc < 0xDC00 || uc > 0xDFFF)
cancelSurrogate();
else {
buf.addChar(((prev - 0xD800) << 10) + (uc - 0xDC00) + 0x10000);
prev = -1;
}
} else if (uc >= 0xD800 && uc <= 0xDBFF)
prev = uc;
else
buf.addChar(uc);
#end
default:
throw "Invalid escape sequence \\" + String.fromCharCode(c) + " at position " + (pos - 1);
}
start = pos;
}
#if !(target.unicode)
// ensure utf8 chars are not cut
else if (c >= 0x80) {
pos++;
if (c >= 0xFC)
pos += 4;
else if (c >= 0xF8)
pos += 3;
else if (c >= 0xF0)
pos += 2;
else if (c >= 0xE0)
pos++;
}
#end
else if (StringTools.isEof(c))
throw "Unclosed string";
}
#if target.unicode
if (prev != -1)
cancelSurrogate();
#end
if (buf == null) {
return str.substr(start, pos - start - 1);
} else {
buf.addSub(str, start, pos - start - 1);
return buf.toString();
}
}
inline function parseNumber(c:Int):Dynamic {
var start = pos - 1;
var minus = c == '-'.code, digit = !minus, zero = c == '0'.code;
var point = false, e = false, pm = false, end = false;
while (true) {
c = nextChar();
switch (c) {
case '0'.code:
if (zero && !point)
invalidNumber(start);
if (minus) {
minus = false;
zero = true;
}
digit = true;
case '1'.code, '2'.code, '3'.code, '4'.code, '5'.code, '6'.code, '7'.code, '8'.code, '9'.code:
if (zero && !point)
invalidNumber(start);
if (minus)
minus = false;
digit = true;
zero = false;
case '.'.code:
if (minus || point || e)
invalidNumber(start);
digit = false;
point = true;
case 'e'.code, 'E'.code:
if (minus || zero || e)
invalidNumber(start);
digit = false;
e = true;
case '+'.code, '-'.code:
if (!e || pm)
invalidNumber(start);
digit = false;
pm = true;
default:
if (!digit)
invalidNumber(start);
pos--;
end = true;
}
if (end)
break;
}
var f = Std.parseFloat(str.substr(start, pos - start));
if(point) {
return f;
} else {
var i = Std.int(f);
return if (i == f) i else f;
}
}
inline function nextChar() {
return StringTools.fastCodeAt(str, pos++);
}
function invalidChar() {
pos--; // rewind
throw "Invalid char " + StringTools.fastCodeAt(str, pos) + " at position " + pos;
}
function invalidNumber(start:Int) {
throw "Invalid number at position " + start + ": " + str.substr(start, pos - start);
}
}

View File

@ -0,0 +1,291 @@
/*
* 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 haxe.format;
/**
An implementation of JSON printer in Haxe.
This class is used by `haxe.Json` when native JSON implementation
is not available.
@see https://haxe.org/manual/std-Json-encoding.html
**/
class JsonPrinter {
/**
Encodes `o`'s value and returns the resulting JSON string.
If `replacer` is given and is not null, it is used to retrieve
actual object to be encoded. The `replacer` function takes two parameters,
the key and the value being encoded. Initial key value is an empty string.
If `space` is given and is not null, the result will be pretty-printed.
Successive levels will be indented by this string.
**/
static public function print(o:Dynamic, ?replacer:(key:Dynamic, value:Dynamic) -> Dynamic, ?space:String):String {
var printer = new JsonPrinter(replacer, space);
printer.write("", o);
return printer.buf.toString();
}
var buf:#if flash flash.utils.ByteArray #else StringBuf #end;
var replacer:(key:Dynamic, value:Dynamic) -> Dynamic;
var indent:String;
var pretty:Bool;
var nind:Int;
function new(replacer:(key:Dynamic, value:Dynamic) -> Dynamic, space:String) {
this.replacer = replacer;
this.indent = space;
this.pretty = space != null;
this.nind = 0;
#if flash
buf = new flash.utils.ByteArray();
buf.endian = flash.utils.Endian.BIG_ENDIAN;
buf.position = 0;
#else
buf = new StringBuf();
#end
}
inline function ipad():Void {
if (pretty)
add(StringTools.lpad('', indent, nind * indent.length));
}
inline function newl():Void {
if (pretty)
addChar('\n'.code);
}
function write(k:Dynamic, v:Dynamic) {
if (replacer != null)
v = replacer(k, v);
switch (Type.typeof(v)) {
case TUnknown:
add('"???"');
case TObject:
objString(v);
case TInt:
add(#if (jvm || hl) Std.string(v) #else v #end);
case TFloat:
add(Math.isFinite(v) ? Std.string(v) : 'null');
case TFunction:
add('"<fun>"');
case TClass(c):
if (c == String)
quote(v);
else if (c == Array) {
var v:Array<Dynamic> = v;
addChar('['.code);
var len = v.length;
var last = len - 1;
for (i in 0...len) {
if (i > 0)
addChar(','.code)
else
nind++;
newl();
ipad();
write(i, v[i]);
if (i == last) {
nind--;
newl();
ipad();
}
}
addChar(']'.code);
} else if (c == haxe.ds.StringMap) {
var v:haxe.ds.StringMap<Dynamic> = v;
var o = {};
for (k in v.keys())
Reflect.setField(o, k, v.get(k));
objString(o);
} else if (c == Date) {
var v:Date = v;
quote(v.toString());
} else
classString(v);
case TEnum(_):
var i:Dynamic = Type.enumIndex(v);
add(i);
case TBool:
add(#if (php || jvm || hl) (v ? 'true' : 'false') #else v #end);
case TNull:
add('null');
}
}
extern inline function addChar(c:Int) {
#if flash
buf.writeByte(c);
#else
buf.addChar(c);
#end
}
extern inline function add(v:String) {
#if flash
// argument is not always a string but will be automatically casted
buf.writeUTFBytes(v);
#else
buf.add(v);
#end
}
function classString(v:Dynamic) {
fieldsString(v, Type.getInstanceFields(Type.getClass(v)));
}
inline function objString(v:Dynamic) {
fieldsString(v, Reflect.fields(v));
}
function fieldsString(v:Dynamic, fields:Array<String>) {
addChar('{'.code);
var len = fields.length;
var last = len - 1;
var first = true;
for (i in 0...len) {
var f = fields[i];
var value = Reflect.field(v, f);
if (Reflect.isFunction(value))
continue;
if (first) {
nind++;
first = false;
} else
addChar(','.code);
newl();
ipad();
quote(f);
addChar(':'.code);
if (pretty)
addChar(' '.code);
write(f, value);
if (i == last) {
nind--;
newl();
ipad();
}
}
addChar('}'.code);
}
function quote(s:String) {
#if neko
if (s.length != neko.Utf8.length(s)) {
quoteUtf8(s);
return;
}
#end
addChar('"'.code);
var i = 0;
var length = s.length;
#if hl
var prev = -1;
#end
while (i < length) {
var c = StringTools.unsafeCodeAt(s, i++);
switch (c) {
case '"'.code:
add('\\"');
case '\\'.code:
add('\\\\');
case '\n'.code:
add('\\n');
case '\r'.code:
add('\\r');
case '\t'.code:
add('\\t');
case 8:
add('\\b');
case 12:
add('\\f');
default:
#if flash
if (c >= 128)
add(String.fromCharCode(c))
else
addChar(c);
#elseif hl
if (prev >= 0) {
if (c >= 0xD800 && c <= 0xDFFF) {
addChar((((prev - 0xD800) << 10) | (c - 0xDC00)) + 0x10000);
prev = -1;
} else {
addChar("".code);
prev = c;
}
} else {
if (c >= 0xD800 && c <= 0xDFFF)
prev = c;
else
addChar(c);
}
#else
addChar(c);
#end
}
}
#if hl
if (prev >= 0)
addChar("".code);
#end
addChar('"'.code);
}
#if neko
function quoteUtf8(s:String) {
var u = new neko.Utf8();
neko.Utf8.iter(s, function(c) {
switch (c) {
case '\\'.code, '"'.code:
u.addChar('\\'.code);
u.addChar(c);
case '\n'.code:
u.addChar('\\'.code);
u.addChar('n'.code);
case '\r'.code:
u.addChar('\\'.code);
u.addChar('r'.code);
case '\t'.code:
u.addChar('\\'.code);
u.addChar('t'.code);
case 8:
u.addChar('\\'.code);
u.addChar('b'.code);
case 12:
u.addChar('\\'.code);
u.addChar('f'.code);
default:
u.addChar(c);
}
});
buf.add('"');
buf.add(u.toString());
buf.add('"');
}
#end
}

View File

@ -0,0 +1,251 @@
/*
* 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 haxe.http;
import haxe.io.Bytes;
private typedef StringKeyValue = {
var name:String;
var value:String;
}
/**
This class can be used to handle Http requests consistently across
platforms. There are two intended usages:
- call `haxe.Http.requestUrl(url)` and receive the result as a `String`
(only available on `sys` targets)
- create a `new haxe.Http(url)`, register your callbacks for `onData`,
`onError` and `onStatus`, then call `request()`.
**/
class HttpBase {
/**
The url of `this` request. It is used only by the `request()` method and
can be changed in order to send the same request to different target
Urls.
**/
public var url:String;
public var responseData(get,never):Null<String>;
public var responseBytes(default,null):Null<Bytes>;
var responseAsString:Null<String>;
var postData:Null<String>;
var postBytes:Null<Bytes>;
var headers:Array<StringKeyValue>;
var params:Array<StringKeyValue>;
final emptyOnData:(String)->Void;
/**
Creates a new Http instance with `url` as parameter.
This does not do a request until `request()` is called.
If `url` is null, the field url must be set to a value before making the
call to `request()`, or the result is unspecified.
(Php) Https (SSL) connections are allowed only if the OpenSSL extension
is enabled.
**/
public function new(url:String) {
this.url = url;
headers = [];
params = [];
emptyOnData = onData;
}
/**
Sets the header identified as `name` to value `value`.
If `name` or `value` are null, the result is unspecified.
This method provides a fluent interface.
**/
public function setHeader(name:String, value:String) {
for (i in 0...headers.length) {
if (headers[i].name == name) {
headers[i] = {name: name, value: value};
return #if hx3compat this #end;
}
}
headers.push({name: name, value: value});
#if hx3compat
return this;
#end
}
public function addHeader(header:String, value:String) {
headers.push({name: header, value: value});
#if hx3compat
return this;
#end
}
/**
Sets the parameter identified as `name` to value `value`.
If `name` or `value` are null, the result is unspecified.
This method provides a fluent interface.
**/
public function setParameter(name:String, value:String) {
for (i in 0...params.length) {
if (params[i].name == name) {
params[i] = {name: name, value: value};
return #if hx3compat this #end;
}
}
params.push({name: name, value: value});
#if hx3compat
return this;
#end
}
public function addParameter(name:String, value:String) {
params.push({name: name, value: value});
#if hx3compat
return this;
#end
}
/**
Sets the post data of `this` Http request to `data` string.
There can only be one post data per request. Subsequent calls to
this method or to `setPostBytes()` overwrite the previously set value.
If `data` is null, the post data is considered to be absent.
This method provides a fluent interface.
**/
public function setPostData(data:Null<String>) {
postData = data;
postBytes = null;
#if hx3compat
return this;
#end
}
/**
Sets the post data of `this` Http request to `data` bytes.
There can only be one post data per request. Subsequent calls to
this method or to `setPostData()` overwrite the previously set value.
If `data` is null, the post data is considered to be absent.
This method provides a fluent interface.
**/
public function setPostBytes(data:Null<Bytes>) {
postBytes = data;
postData = null;
#if hx3compat
return this;
#end
}
/**
Sends `this` Http request to the Url specified by `this.url`.
If `post` is true, the request is sent as POST request, otherwise it is
sent as GET request.
Depending on the outcome of the request, this method calls the
`onStatus()`, `onError()`, `onData()` or `onBytes()` callback functions.
If `this.url` is null, the result is unspecified.
If `this.url` is an invalid or inaccessible Url, the `onError()` callback
function is called.
[js] If `this.async` is false, the callback functions are called before
this method returns.
**/
public function request(?post:Bool):Void {
throw new haxe.exceptions.NotImplementedException();
}
/**
This method is called upon a successful request, with `data` containing
the result String.
The intended usage is to bind it to a custom function:
`httpInstance.onData = function(data) { // handle result }`
**/
public dynamic function onData(data:String) {}
/**
This method is called upon a successful request, with `data` containing
the result String.
The intended usage is to bind it to a custom function:
`httpInstance.onBytes = function(data) { // handle result }`
**/
public dynamic function onBytes(data:Bytes) {}
/**
This method is called upon a request error, with `msg` containing the
error description.
The intended usage is to bind it to a custom function:
`httpInstance.onError = function(msg) { // handle error }`
**/
public dynamic function onError(msg:String) {}
/**
This method is called upon a Http status change, with `status` being the
new status.
The intended usage is to bind it to a custom function:
`httpInstance.onStatus = function(status) { // handle status }`
**/
public dynamic function onStatus(status:Int) {}
/**
Override this if extending `haxe.Http` with overriding `onData`
**/
function hasOnData():Bool {
return !Reflect.compareMethods(onData, emptyOnData);
}
function success(data:Bytes) {
responseBytes = data;
responseAsString = null;
if (hasOnData()) {
onData(responseData);
}
onBytes(responseBytes);
}
function get_responseData() {
if (responseAsString == null && responseBytes != null) {
#if neko
responseAsString = neko.Lib.stringReference(responseBytes);
#else
responseAsString = responseBytes.getString(0, responseBytes.length, UTF8);
#end
}
return responseAsString;
}
}

View File

@ -0,0 +1,160 @@
/*
* 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 haxe.http;
#if js
import js.html.XMLHttpRequestResponseType;
import js.html.Blob;
import haxe.io.Bytes;
class HttpJs extends haxe.http.HttpBase {
public var async:Bool;
public var withCredentials:Bool;
var req:js.html.XMLHttpRequest;
public function new(url:String) {
async = true;
withCredentials = false;
super(url);
}
/**
Cancels `this` Http request if `request` has been called and a response
has not yet been received.
**/
public function cancel() {
if (req == null)
return;
req.abort();
req = null;
}
public override function request(?post:Bool) {
this.responseAsString = null;
this.responseBytes = null;
var r = req = js.Browser.createXMLHttpRequest();
var onreadystatechange = function(_) {
if (r.readyState != 4)
return;
var s = try r.status catch (e:Dynamic) null;
if (s == 0 && js.Browser.supported && js.Browser.location != null) {
// If the request is local and we have data: assume a success (jQuery approach):
var protocol = js.Browser.location.protocol.toLowerCase();
var rlocalProtocol = ~/^(?:about|app|app-storage|.+-extension|file|res|widget):$/;
var isLocal = rlocalProtocol.match(protocol);
if (isLocal) {
s = r.response != null ? 200 : 404;
}
}
if (s == js.Lib.undefined)
s = null;
if (s != null)
onStatus(s);
if (s != null && s >= 200 && s < 400) {
req = null;
success(Bytes.ofData(r.response));
} else if (s == null || (s == 0 && r.response == null)) {
req = null;
onError("Failed to connect or resolve host");
} else
switch (s) {
case 12029:
req = null;
onError("Failed to connect to host");
case 12007:
req = null;
onError("Unknown host");
default:
req = null;
responseBytes = r.response != null ? Bytes.ofData(r.response) : null;
onError("Http Error #" + r.status);
}
};
if (async)
r.onreadystatechange = onreadystatechange;
var uri:Null<Any> = switch [postData, postBytes] {
case [null, null]: null;
case [str, null]: str;
case [null, bytes]: new Blob([bytes.getData()]);
case _: null;
}
if (uri != null)
post = true;
else
for (p in params) {
if (uri == null)
uri = "";
else
uri = uri + "&";
uri = uri + StringTools.urlEncode(p.name) + "=" + StringTools.urlEncode(p.value);
}
try {
if (post)
r.open("POST", url, async);
else if (uri != null) {
var question = url.split("?").length <= 1;
r.open("GET", url + (if (question) "?" else "&") + uri, async);
uri = null;
} else
r.open("GET", url, async);
r.responseType = ARRAYBUFFER;
} catch (e:Dynamic) {
req = null;
onError(e.toString());
return;
}
r.withCredentials = withCredentials;
if (!Lambda.exists(headers, function(h) return h.name == "Content-Type") && post && postData == null)
r.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
for (h in headers)
r.setRequestHeader(h.name, h.value);
r.send(uri);
if (!async)
onreadystatechange(null);
}
/**
Makes a synchronous request to `url`.
This creates a new Http instance and makes a GET request by calling its
`request(false)` method.
If `url` is null, the result is unspecified.
**/
public static function requestUrl(url:String):String {
var h = new Http(url);
h.async = false;
var r = null;
h.onData = function(d) {
r = d;
}
h.onError = function(e) {
throw e;
}
h.request(false);
return r;
}
}
#end

View File

@ -0,0 +1,84 @@
package haxe.http;
/**
HTTP defines methods (sometimes referred to as _verbs_) to indicate the desired action to be
performed on the identified resource. What this resource represents, whether pre-existing data
or data that is generated dynamically, depends on the implementation of the server.
Often, the resource corresponds to a file or the output of an executable residing on the server.
The HTTP/1.0 specification defined the `GET`, `POST` and `HEAD` methods and the HTTP/1.1
specification added 5 new methods: `OPTIONS`, `PUT`, `DELETE`, `TRACE` and `CONNECT`.
By being specified in these documents their semantics are well known and can be depended upon.
Any client can use any method and the server can be configured to support any combination of methods.
If a method is unknown to an intermediate it will be treated as an unsafe and non-idempotent method.
There is no limit to the number of methods that can be defined and this allows for future methods to
be specified without breaking existing infrastructure.
**/
enum abstract HttpMethod(String) from String to String {
/**
The `POST` method requests that the server accept the entity enclosed in the request as
a new subordinate of the web resource identified by the URI.
The data `POST`ed might be, for example, an annotation for existing resources;
a message for a bulletin board, newsgroup, mailing list, or comment thread;
a block of data that is the result of submitting a web form to a data-handling process;
or an item to add to a database.
**/
var Post = 'POST';
/**
The `GET` method requests a representation of the specified resource.
Requests using `GET` should only retrieve data and should have no other effect.
(This is also true of some other HTTP methods.) The W3C has published guidance
principles on this distinction, saying, _"Web application design should be informed
by the above principles, but also by the relevant limitations."_
See safe methods below.
**/
var Get = 'GET';
/**
The `HEAD` method asks for a response identical to that of a `GET` request,
but without the response body. This is useful for retrieving meta-information
written in response headers, without having to transport the entire content.
**/
var Head = 'HEAD';
/**
The `PUT` method requests that the enclosed entity be stored under the supplied URI.
If the URI refers to an already existing resource, it is modified; if the URI does
not point to an existing resource, then the server can create the resource with that URI.
**/
var Put = 'PUT';
/**
The `DELETE` method deletes the specified resource.
**/
var Delete = 'DELETE';
/**
The `TRACE` method echoes the received request so that a client can see
what (if any) changes or additions have been made by intermediate servers.
**/
var Trace = 'TRACE';
/**
The `OPTIONS` method returns the HTTP methods that the server supports for the
specified URL. This can be used to check the functionality of a web server by
requesting `*` instead of a specific resource.
**/
var Options = 'OPTIONS';
/**
The `CONNECT` method converts the request connection to a transparent TCP/IP tunnel,
usually to facilitate SSL-encrypted communication (HTTPS) through an unencrypted HTTP proxy.
**/
var Connect = 'CONNECT';
/**
The `PATCH` method applies partial modifications to a resource.
**/
var Patch = 'PATCH';
}

View File

@ -0,0 +1,119 @@
/*
* 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 haxe.http;
#if nodejs
import js.node.Buffer;
import haxe.io.Bytes;
class HttpNodeJs extends haxe.http.HttpBase {
var req:js.node.http.ClientRequest;
public function new(url:String) {
super(url);
}
/**
Cancels `this` Http request if `request` has been called and a response
has not yet been received.
**/
public function cancel() {
if (req == null)
return;
req.abort();
req = null;
}
public override function request(?post:Bool) {
responseAsString = null;
responseBytes = null;
var parsedUrl = new js.node.url.URL(url);
var secure = (parsedUrl.protocol == "https:");
var host = parsedUrl.hostname;
var path = parsedUrl.pathname;
var port = if (parsedUrl.port != null) Std.parseInt(parsedUrl.port) else (secure ? 443 : 80);
var h:Dynamic = {};
for (i in headers) {
var arr = Reflect.field(h, i.name);
if (arr == null) {
arr = new Array<String>();
Reflect.setField(h, i.name, arr);
}
arr.push(i.value);
}
if (postData != null || postBytes != null)
post = true;
var uri = null;
for (p in params) {
if (uri == null)
uri = "";
else
uri += "&";
uri += StringTools.urlEncode(p.name) + "=" + StringTools.urlEncode(p.value);
}
var question = path.split("?").length <= 1;
if (uri != null)
path += (if (question) "?" else "&") + uri;
var opts = {
protocol: parsedUrl.protocol,
hostname: host,
port: port,
method: post ? 'POST' : 'GET',
path: path,
headers: h
};
function httpResponse(res) {
res.setEncoding('binary');
var s = res.statusCode;
if (s != null)
onStatus(s);
var data = [];
res.on('data', function(chunk:String) {
data.push(Buffer.from(chunk, 'binary'));
});
res.on('end', function(_) {
var buf = (data.length == 1 ? data[0] : Buffer.concat(data));
responseBytes = Bytes.ofData(buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength));
req = null;
if (s != null && s >= 200 && s < 400) {
success(responseBytes);
} else {
onError("Http Error #" + s);
}
});
}
req = secure ? js.node.Https.request(untyped opts, httpResponse) : js.node.Http.request(untyped opts, httpResponse);
if (post)
if (postData != null) {
req.write(postData);
} else if(postBytes != null) {
req.setHeader("Content-Length", '${postBytes.length}');
req.write(Buffer.from(postBytes.getData()));
}
req.end();
}
}
#end

View File

@ -0,0 +1,68 @@
package haxe.http;
/**
HTTP Request Status
**/
enum abstract HttpStatus(Int) from Int to Int {
var Continue = 100;
var SwitchingProtocols = 101;
var Processing = 102;
var OK = 200;
var Created = 201;
var Accepted = 202;
var NonAuthoritativeInformation = 203;
var NoContent = 204;
var ResetContent = 205;
var PartialContent = 206;
var MultiStatus = 207;
var AlreadyReported = 208;
var IMUsed = 226;
var MultipleChoices = 300;
var MovedPermanently = 301;
var Found = 302;
var SeeOther = 303;
var NotModified = 304;
var UseProxy = 305;
var SwitchProxy = 306;
var TemporaryRedirect = 307;
var PermanentRedirect = 308;
var BadRequest = 400;
var Unauthorized = 401;
var PaymentRequired = 402;
var Forbidden = 403;
var NotFound = 404;
var MethodNotAllowed = 405;
var NotAcceptable = 406;
var ProxyAuthenticationRequired = 407;
var RequestTimeout = 408;
var Conflict = 409;
var Gone = 410;
var LengthRequired = 411;
var PreconditionFailed = 412;
var PayloadTooLarge = 413;
var URITooLong = 414;
var UnsupportedMediaType = 415;
var RangeNotSatisfiable = 416;
var ExpectationFailed = 417;
var ImATeapot = 418;
var MisdirectedRequest = 421;
var UnprocessableEntity = 422;
var Locked = 423;
var FailedDependency = 424;
var UpgradeRequired = 426;
var PreconditionRequired = 428;
var TooManyRequests = 429;
var RequestHeaderFieldsTooLarge = 431;
var UnavailableForLegalReasons = 451;
var InternalServerError = 500;
var NotImplemented = 501;
var BadGateway = 502;
var ServiceUnavailable = 503;
var GatewayTimeout = 504;
var HTTPVersionNotSupported = 505;
var VariantAlsoNegotiates = 506;
var InsufficientStorage = 507;
var LoopDetected = 508;
var NotExtended = 510;
var NetworkAuthenticationRequired = 511;
}

View File

@ -0,0 +1,96 @@
/*
* 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 haxe.io;
typedef ArrayBufferViewData = ArrayBufferViewImpl;
class ArrayBufferViewImpl {
public var bytes:haxe.io.Bytes;
public var byteOffset:Int;
public var byteLength:Int;
public function new(bytes, pos, length) {
this.bytes = bytes;
this.byteOffset = pos;
this.byteLength = length;
}
public function sub(begin:Int, ?length:Int) {
if (length == null)
length = byteLength - begin;
if (begin < 0 || length < 0 || begin + length > byteLength)
throw Error.OutsideBounds;
return new ArrayBufferViewImpl(bytes, byteOffset + begin, length);
}
public function subarray(?begin:Int, ?end:Int) {
if (begin == null)
begin = 0;
if (end == null)
end = byteLength - begin;
return sub(begin, end - begin);
}
}
abstract ArrayBufferView(ArrayBufferViewData) {
public var buffer(get, never):haxe.io.Bytes;
public var byteOffset(get, never):Int;
public var byteLength(get, never):Int;
public inline function new(size:Int) {
this = new ArrayBufferViewData(haxe.io.Bytes.alloc(size), 0, size);
}
inline function get_byteOffset():Int
return this.byteOffset;
inline function get_byteLength():Int
return this.byteLength;
inline function get_buffer():haxe.io.Bytes
return this.bytes;
public inline function sub(begin:Int, ?length:Int):ArrayBufferView {
return fromData(this.sub(begin, length));
}
public inline function subarray(?begin:Int, ?end:Int):ArrayBufferView {
return fromData(this.subarray(begin, end));
}
public inline function getData():ArrayBufferViewData {
return this;
}
public static inline function fromData(a:ArrayBufferViewData):ArrayBufferView {
return cast a;
}
public static function fromBytes(bytes:haxe.io.Bytes, pos = 0, ?length:Int):ArrayBufferView {
if (length == null)
length = bytes.length - pos;
if (pos < 0 || length < 0 || pos + length > bytes.length)
throw Error.OutsideBounds;
return fromData(new ArrayBufferViewData(bytes, pos, length));
}
}

View File

@ -0,0 +1,64 @@
/*
* 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 haxe.io;
class BufferInput extends haxe.io.Input {
public var i:haxe.io.Input;
public var buf:haxe.io.Bytes;
public var available:Int;
public var pos:Int;
public function new(i, buf, ?pos = 0, ?available = 0) {
this.i = i;
this.buf = buf;
this.pos = pos;
this.available = available;
}
public function refill() {
if (pos > 0) {
buf.blit(0, buf, pos, available);
pos = 0;
}
available += i.readBytes(buf, available, buf.length - available);
}
override function readByte() {
if (available == 0)
refill();
var c = buf.get(pos);
pos++;
available--;
return c;
}
override function readBytes(buf:haxe.io.Bytes, pos:Int, len:Int) {
if (available == 0)
refill();
var size = if (len > available) available else len;
buf.blit(pos, this.buf, this.pos, size);
this.pos += size;
this.available -= size;
return size;
}
}

View File

@ -0,0 +1,707 @@
/*
* 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 haxe.io;
#if cpp
using cpp.NativeArray;
#end
class Bytes {
public var length(default, null):Int;
var b:BytesData;
function new(length, b) {
this.length = length;
this.b = b;
#if flash
b.endian = flash.utils.Endian.LITTLE_ENDIAN;
#end
}
/**
Returns the byte at index `pos`.
**/
public inline function get(pos:Int):Int {
#if neko
return untyped $sget(b, pos);
#elseif flash
return b[pos];
#elseif cpp
return untyped b[pos];
#elseif java
return untyped b[pos] & 0xFF;
#elseif python
return python.Syntax.arrayAccess(b, pos);
#else
return b[pos];
#end
}
/**
Stores the given byte `v` at the given position `pos`.
**/
public inline function set(pos:Int, v:Int):Void {
#if neko
untyped $sset(b, pos, v);
#elseif flash
b[pos] = v;
#elseif cpp
untyped b[pos] = v;
#elseif java
b[pos] = cast v;
#elseif cs
b[pos] = cast v;
#elseif python
python.Syntax.arraySet(b, pos, v & 0xFF);
#else
b[pos] = v & 0xFF;
#end
}
/**
Copies `len` bytes from `src` into this instance.
@param pos Zero-based location in `this` instance at which to start writing
bytes.
@param src Source `Bytes` instance from which to copy bytes.
@param srcpos Zero-based location at `src` from which bytes will be copied.
@param len Number of bytes to be copied.
**/
public function blit(pos:Int, src:Bytes, srcpos:Int, len:Int):Void {
#if !neko
if (pos < 0 || srcpos < 0 || len < 0 || pos + len > length || srcpos + len > src.length)
throw Error.OutsideBounds;
#end
#if neko
try
untyped $sblit(b, pos, src.b, srcpos, len)
catch (e:Dynamic)
throw Error.OutsideBounds;
#elseif flash
b.position = pos;
if (len > 0)
b.writeBytes(src.b, srcpos, len);
#elseif java
java.lang.System.arraycopy(src.b, srcpos, b, pos, len);
#elseif cs
cs.system.Array.Copy(src.b, srcpos, b, pos, len);
#elseif python
python.Syntax.code("self.b[{0}:{0}+{1}] = src.b[srcpos:srcpos+{1}]", pos, len);
#elseif cpp
b.blit(pos, src.b, srcpos, len);
#else
var b1 = b;
var b2 = src.b;
if (b1 == b2 && pos > srcpos) {
var i = len;
while (i > 0) {
i--;
b1[i + pos] = b2[i + srcpos];
}
return;
}
for (i in 0...len)
b1[i + pos] = b2[i + srcpos];
#end
}
/**
Sets `len` consecutive bytes starting from index `pos` of `this` instance
to `value`.
**/
public function fill(pos:Int, len:Int, value:Int) {
#if flash
var v4 = value & 0xFF;
v4 |= v4 << 8;
v4 |= v4 << 16;
b.position = pos;
for (i in 0...len >> 2)
b.writeUnsignedInt(v4);
pos += len & ~3;
for (i in 0...len & 3)
set(pos++, value);
#elseif cpp
untyped __global__.__hxcpp_memory_memset(b, pos, len, value);
#else
for (i in 0...len)
set(pos++, value);
#end
}
/**
Returns a new `Bytes` instance that contains a copy of `len` bytes of
`this` instance, starting at index `pos`.
**/
public function sub(pos:Int, len:Int):Bytes {
#if !neko
if (pos < 0 || len < 0 || pos + len > length)
throw Error.OutsideBounds;
#end
#if neko
return try new Bytes(len, untyped __dollar__ssub(b, pos, len)) catch (e:Dynamic) throw Error.OutsideBounds;
#elseif flash
b.position = pos;
var b2 = new flash.utils.ByteArray();
b.readBytes(b2, 0, len);
return new Bytes(len, b2);
#elseif java
var newarr = new java.NativeArray(len);
java.lang.System.arraycopy(b, pos, newarr, 0, len);
return new Bytes(len, newarr);
#elseif cs
var newarr = new cs.NativeArray(len);
cs.system.Array.Copy(b, pos, newarr, 0, len);
return new Bytes(len, newarr);
#elseif python
return new Bytes(len, python.Syntax.arrayAccess(b, pos, pos + len));
#else
return new Bytes(len, b.slice(pos, pos + len));
#end
}
/**
Returns `0` if the bytes of `this` instance and the bytes of `other` are
identical.
Returns a negative value if the `length` of `this` instance is less than
the `length` of `other`, or a positive value if the `length` of `this`
instance is greater than the `length` of `other`.
In case of equal `length`s, returns a negative value if the first different
value in `other` is greater than the corresponding value in `this`
instance; otherwise returns a positive value.
**/
public function compare(other:Bytes):Int {
#if neko
return untyped __dollar__compare(b, other.b);
#elseif flash
var len = (length < other.length) ? length : other.length;
var b1 = b;
var b2 = other.b;
b1.position = 0;
b2.position = 0;
b1.endian = flash.utils.Endian.BIG_ENDIAN;
b2.endian = flash.utils.Endian.BIG_ENDIAN;
for (i in 0...len >> 2)
if (b1.readUnsignedInt() != b2.readUnsignedInt()) {
b1.position -= 4;
b2.position -= 4;
var d = b1.readUnsignedInt() - b2.readUnsignedInt();
b1.endian = flash.utils.Endian.LITTLE_ENDIAN;
b2.endian = flash.utils.Endian.LITTLE_ENDIAN;
return d;
}
for (i in 0...len & 3)
if (b1.readUnsignedByte() != b2.readUnsignedByte()) {
b1.endian = flash.utils.Endian.LITTLE_ENDIAN;
b2.endian = flash.utils.Endian.LITTLE_ENDIAN;
return b1[b1.position - 1] - b2[b2.position - 1];
}
b1.endian = flash.utils.Endian.LITTLE_ENDIAN;
b2.endian = flash.utils.Endian.LITTLE_ENDIAN;
return length - other.length;
// #elseif cs
// TODO: memcmp if unsafe flag is on
#elseif cpp
return b.memcmp(other.b);
#else
var b1 = b;
var b2 = other.b;
var len = (length < other.length) ? length : other.length;
for (i in 0...len)
if (b1[i] != b2[i])
return untyped b1[i] - b2[i];
return length - other.length;
#end
}
/**
Returns the IEEE double-precision value at the given position `pos` (in
little-endian encoding). Result is unspecified if `pos` is outside the
bounds.
**/
#if (neko_v21 || (cpp && !cppia) || flash)
inline
#end
public function getDouble(pos:Int):Float {
#if neko_v21
return untyped $sgetd(b, pos, false);
#elseif flash
b.position = pos;
return b.readDouble();
#elseif cpp
if (pos < 0 || pos + 8 > length)
throw Error.OutsideBounds;
return untyped __global__.__hxcpp_memory_get_double(b, pos);
#else
return FPHelper.i64ToDouble(getInt32(pos), getInt32(pos + 4));
#end
}
/**
Returns the IEEE single-precision value at the given position `pos` (in
little-endian encoding). Result is unspecified if `pos` is outside the
bounds.
**/
#if (neko_v21 || (cpp && !cppia) || flash)
inline
#end
public function getFloat(pos:Int):Float {
#if neko_v21
return untyped $sgetf(b, pos, false);
#elseif flash
b.position = pos;
return b.readFloat();
#elseif cpp
if (pos < 0 || pos + 4 > length)
throw Error.OutsideBounds;
return untyped __global__.__hxcpp_memory_get_float(b, pos);
#else
return FPHelper.i32ToFloat(getInt32(pos));
#end
}
/**
Stores the given IEEE double-precision value `v` at the given position
`pos` in little-endian encoding. Result is unspecified if writing outside
of bounds.
**/
#if (neko_v21 || flash)
inline
#end
public function setDouble(pos:Int, v:Float):Void {
#if neko_v21
untyped $ssetd(b, pos, v, false);
#elseif neko
untyped $sblit(b, pos, FPHelper._double_bytes(v, false), 0, 8);
#elseif flash
b.position = pos;
b.writeDouble(v);
#elseif cpp
if (pos < 0 || pos + 8 > length)
throw Error.OutsideBounds;
untyped __global__.__hxcpp_memory_set_double(b, pos, v);
#else
var i = FPHelper.doubleToI64(v);
setInt32(pos, i.low);
setInt32(pos + 4, i.high);
#end
}
/**
Stores the given IEEE single-precision value `v` at the given position
`pos` in little-endian encoding. Result is unspecified if writing outside
of bounds.
**/
#if (neko_v21 || flash)
inline
#end
public function setFloat(pos:Int, v:Float):Void {
#if neko_v21
untyped $ssetf(b, pos, v, false);
#elseif neko
untyped $sblit(b, pos, FPHelper._float_bytes(v, false), 0, 4);
#elseif flash
b.position = pos;
b.writeFloat(v);
#elseif cpp
if (pos < 0 || pos + 4 > length)
throw Error.OutsideBounds;
untyped __global__.__hxcpp_memory_set_float(b, pos, v);
#else
setInt32(pos, FPHelper.floatToI32(v));
#end
}
/**
Returns the 16-bit unsigned integer at the given position `pos` (in
little-endian encoding).
**/
public inline function getUInt16(pos:Int):Int {
#if neko_v21
return untyped $sget16(b, pos, false);
#else
return get(pos) | (get(pos + 1) << 8);
#end
}
/**
Stores the given 16-bit unsigned integer `v` at the given position `pos`
(in little-endian encoding).
**/
public inline function setUInt16(pos:Int, v:Int):Void {
#if neko_v21
untyped $sset16(b, pos, v, false);
#else
set(pos, v);
set(pos + 1, v >> 8);
#end
}
/**
Returns the 32-bit integer at the given position `pos` (in little-endian
encoding).
**/
public inline function getInt32(pos:Int):Int {
#if neko_v21
return untyped $sget32(b, pos, false);
#elseif python
var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos + 3) << 24);
return if (v & 0x80000000 != 0) v | 0x80000000 else v;
#elseif lua
var v = get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos + 3) << 24);
return lua.Boot.clampInt32(if (v & 0x80000000 != 0) v | 0x80000000 else v);
#else
return get(pos) | (get(pos + 1) << 8) | (get(pos + 2) << 16) | (get(pos + 3) << 24);
#end
}
/**
Returns the 64-bit integer at the given position `pos` (in little-endian
encoding).
**/
public inline function getInt64(pos:Int):haxe.Int64 {
return haxe.Int64.make(getInt32(pos + 4), getInt32(pos));
}
/**
Stores the given 32-bit integer `v` at the given position `pos` (in
little-endian encoding).
**/
public inline function setInt32(pos:Int, v:Int):Void {
#if neko_v21
untyped $sset32(b, pos, v, false);
#else
set(pos, v);
set(pos + 1, v >> 8);
set(pos + 2, v >> 16);
set(pos + 3, v >>> 24);
#end
}
/**
Stores the given 64-bit integer `v` at the given position `pos` (in
little-endian encoding).
**/
public inline function setInt64(pos:Int, v:haxe.Int64):Void {
setInt32(pos, v.low);
setInt32(pos + 4, v.high);
}
/**
Returns the `len`-bytes long string stored at the given position `pos`,
interpreted with the given `encoding` (UTF-8 by default).
**/
public function getString(pos:Int, len:Int, ?encoding:Encoding):String {
if (encoding == null)
encoding == UTF8;
#if !neko
if (pos < 0 || len < 0 || pos + len > length)
throw Error.OutsideBounds;
#end
#if neko
return try new String(untyped __dollar__ssub(b, pos, len)) catch (e:Dynamic) throw Error.OutsideBounds;
#elseif flash
b.position = pos;
return encoding == RawNative ? b.readMultiByte(len, "unicode") : b.readUTFBytes(len);
#elseif cpp
var result:String = "";
untyped __global__.__hxcpp_string_of_bytes(b, result, pos, len);
return result;
#elseif cs
switch (encoding) {
case UTF8 | null:
return cs.system.text.Encoding.UTF8.GetString(b, pos, len);
case RawNative:
return cs.system.text.Encoding.Unicode.GetString(b, pos, len);
}
#elseif java
try {
switch (encoding) {
case UTF8 | null:
return new String(b, pos, len, "UTF-8");
case RawNative:
return new String(b, pos, len, "UTF-16LE");
}
} catch (e:Dynamic) {
throw e;
}
#elseif python
return python.Syntax.code("self.b[{0}:{0}+{1}].decode('UTF-8','replace')", pos, len);
#elseif lua
if (b.length - pos <= lua.Boot.MAXSTACKSIZE) {
var end:Int = cast Math.min(b.length, pos + len) - 1;
return lua.NativeStringTools.char(lua.TableTools.unpack(untyped b, pos, end));
} else {
var tbl:lua.Table<Int, String> = lua.Table.create();
for (idx in pos...pos + len) {
lua.Table.insert(tbl, lua.NativeStringTools.char(b[idx]));
}
return lua.Table.concat(tbl, '');
}
#else
var s = "";
var b = b;
var fcc = String.fromCharCode;
var i = pos;
var max = pos + len;
// utf8-decode and utf16-encode
while (i < max) {
var c = b[i++];
if (c < 0x80) {
if (c == 0)
break;
s += fcc(c);
} else if (c < 0xE0)
s += fcc(((c & 0x3F) << 6) | (b[i++] & 0x7F));
else if (c < 0xF0) {
var c2 = b[i++];
s += fcc(((c & 0x1F) << 12) | ((c2 & 0x7F) << 6) | (b[i++] & 0x7F));
} else {
var c2 = b[i++];
var c3 = b[i++];
var u = ((c & 0x0F) << 18) | ((c2 & 0x7F) << 12) | ((c3 & 0x7F) << 6) | (b[i++] & 0x7F);
// surrogate pair
s += fcc((u >> 10) + 0xD7C0);
s += fcc((u & 0x3FF) | 0xDC00);
}
}
return s;
#end
}
@:deprecated("readString is deprecated, use getString instead")
@:noCompletion
public inline function readString(pos:Int, len:Int):String {
return getString(pos, len);
}
/**
Returns a `String` representation of the bytes interpreted as UTF-8.
**/
public function toString():String {
#if neko
return new String(untyped __dollar__ssub(b, 0, length));
#elseif flash
b.position = 0;
return b.toString();
#elseif cs
return cs.system.text.Encoding.UTF8.GetString(b, 0, length);
#elseif java
try {
return new String(b, 0, length, "UTF-8");
} catch (e:Dynamic)
throw e;
#else
return getString(0, length);
#end
}
/**
Returns a hexadecimal `String` representation of the bytes of `this`
instance.
**/
public function toHex():String {
var s = new StringBuf();
var chars = [];
var str = "0123456789abcdef";
for (i in 0...str.length)
chars.push(str.charCodeAt(i));
for (i in 0...length) {
var c = get(i);
s.addChar(chars[c >> 4]);
s.addChar(chars[c & 15]);
}
return s.toString();
}
/**
Returns the bytes of `this` instance as `BytesData`.
**/
public inline function getData():BytesData {
return b;
}
/**
Returns a new `Bytes` instance with the given `length`. The values of the
bytes are not initialized and may not be zero.
**/
public static function alloc(length:Int):Bytes {
#if neko
return new Bytes(length, untyped __dollar__smake(length));
#elseif flash
var b = new flash.utils.ByteArray();
b.length = length;
return new Bytes(length, b);
#elseif cpp
var a = new BytesData();
if (length > 0)
cpp.NativeArray.setSize(a, length);
return new Bytes(length, a);
#elseif cs
return new Bytes(length, new cs.NativeArray(length));
#elseif java
return new Bytes(length, new java.NativeArray(length));
#elseif python
return new Bytes(length, new python.Bytearray(length));
#else
var a = new Array();
for (i in 0...length)
a.push(0);
return new Bytes(length, a);
#end
}
/**
Returns the `Bytes` representation of the given `String`, using the
specified encoding (UTF-8 by default).
**/
@:pure
public static function ofString(s:String, ?encoding:Encoding):Bytes {
#if neko
return new Bytes(s.length, untyped __dollar__ssub(s.__s, 0, s.length));
#elseif flash
var b = new flash.utils.ByteArray();
if (encoding == RawNative)
b.writeMultiByte(s, "unicode")
else
b.writeUTFBytes(s);
return new Bytes(b.length, b);
#elseif cpp
var a = new BytesData();
untyped __global__.__hxcpp_bytes_of_string(a, s);
return new Bytes(a.length, a);
#elseif cs
var b = switch (encoding) {
case UTF8 | null:
cs.system.text.Encoding.UTF8.GetBytes(s);
case RawNative:
cs.system.text.Encoding.Unicode.GetBytes(s);
};
return new Bytes(b.Length, b);
#elseif java
try {
var b:BytesData = switch (encoding) {
case UTF8 | null:
@:privateAccess s.getBytes("UTF-8");
case RawNative:
@:privateAccess s.getBytes("UTF-16LE");
};
return new Bytes(b.length, b);
} catch (e:Dynamic) {
throw e;
}
#elseif python
var b:BytesData = new python.Bytearray(s, "UTF-8");
return new Bytes(b.length, b);
#elseif lua
var bytes = [
for (i in 0...lua.NativeStringTools.len(s)) {
lua.NativeStringTools.byte(s, i + 1);
}
];
return new Bytes(bytes.length, bytes);
#else
var a = new Array();
// utf16-decode and utf8-encode
var i = 0;
while (i < s.length) {
var c:Int = StringTools.fastCodeAt(s, i++);
// surrogate pair
if (0xD800 <= c && c <= 0xDBFF)
c = (c - 0xD7C0 << 10) | (StringTools.fastCodeAt(s, i++) & 0x3FF);
if (c <= 0x7F)
a.push(c);
else if (c <= 0x7FF) {
a.push(0xC0 | (c >> 6));
a.push(0x80 | (c & 63));
} else if (c <= 0xFFFF) {
a.push(0xE0 | (c >> 12));
a.push(0x80 | ((c >> 6) & 63));
a.push(0x80 | (c & 63));
} else {
a.push(0xF0 | (c >> 18));
a.push(0x80 | ((c >> 12) & 63));
a.push(0x80 | ((c >> 6) & 63));
a.push(0x80 | (c & 63));
}
}
return new Bytes(a.length, a);
#end
}
/**
Returns the `Bytes` representation of the given `BytesData`.
**/
public static function ofData(b:BytesData) {
#if flash
return new Bytes(b.length, b);
#elseif neko
return new Bytes(untyped __dollar__ssize(b), b);
#elseif cs
return new Bytes(b.Length, b);
#else
return new Bytes(b.length, b);
#end
}
/**
Converts the given hexadecimal `String` to `Bytes`. `s` must be a string of
even length consisting only of hexadecimal digits. For example:
`"0FDA14058916052309"`.
**/
public static function ofHex(s:String):Bytes {
var len:Int = s.length;
if ((len & 1) != 0)
throw "Not a hex string (odd number of digits)";
var ret:Bytes = Bytes.alloc(len >> 1);
for (i in 0...ret.length) {
var high = StringTools.fastCodeAt(s, i * 2);
var low = StringTools.fastCodeAt(s, i * 2 + 1);
high = (high & 0xF) + ((high & 0x40) >> 6) * 9;
low = (low & 0xF) + ((low & 0x40) >> 6) * 9;
ret.set(i, ((high << 4) | low) & 0xFF);
}
return ret;
}
/**
Reads the `pos`-th byte of the given `b` bytes, in the most efficient way
possible. Behavior when reading outside of the available data is
unspecified.
**/
public inline static function fastGet(b:BytesData, pos:Int):Int {
#if neko
return untyped __dollar__sget(b, pos);
#elseif flash
return b[pos];
#elseif cpp
return untyped b.unsafeGet(pos);
#elseif java
return untyped b[pos] & 0xFF;
#else
return b[pos];
#end
}
}

View File

@ -0,0 +1,225 @@
/*
* 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 haxe.io;
class BytesBuffer {
#if neko
var b:Dynamic; // neko string buffer
#elseif flash
var b:flash.utils.ByteArray;
#elseif cpp
var b:BytesData;
#elseif cs
var b:cs.system.io.MemoryStream;
#elseif java
var b:java.io.ByteArrayOutputStream;
#elseif python
var b:python.Bytearray;
#else
var b:Array<Int>;
#end
/** The length of the buffer in bytes. **/
public var length(get, never):Int;
public function new() {
#if neko
b = untyped StringBuf.__make();
#elseif flash
b = new flash.utils.ByteArray();
b.endian = flash.utils.Endian.LITTLE_ENDIAN;
#elseif cpp
b = new BytesData();
#elseif cs
b = new cs.system.io.MemoryStream();
#elseif java
b = new java.io.ByteArrayOutputStream();
#elseif python
b = new python.Bytearray();
#else
b = new Array();
#end
}
inline function get_length():Int {
#if neko
return untyped __dollar__ssize(StringBuf.__to_string(b));
#elseif cs
return haxe.Int64.toInt(b.Length);
#elseif java
return b.size();
#else
return b.length;
#end
}
public inline function addByte(byte:Int) {
#if neko
untyped StringBuf.__add_char(b, byte);
#elseif flash
b.writeByte(byte);
#elseif cpp
b.push(untyped byte);
#elseif cs
b.WriteByte(cast byte);
#elseif java
b.write(byte);
#elseif python
b.append(byte);
#else
b.push(byte);
#end
}
public inline function add(src:Bytes) {
#if neko
untyped StringBuf.__add(b, src.getData());
#elseif flash
b.writeBytes(src.getData());
#elseif cs
b.Write(src.getData(), 0, src.length);
#elseif java
b.write(src.getData(), 0, src.length);
#elseif js
var b1 = b;
var b2 = @:privateAccess src.b;
for (i in 0...src.length)
b.push(b2[i]);
#elseif python
b.extend(src.getData());
#else
var b1 = b;
var b2 = src.getData();
for (i in 0...src.length)
b.push(b2[i]);
#end
}
public inline function addString(v:String, ?encoding:Encoding) {
#if neko
untyped StringBuf.__add(b, v.__s);
#elseif flash
if (encoding == RawNative)
b.writeMultiByte(v, "unicode")
else
b.writeUTFBytes(v);
#elseif python
b.extend(new python.Bytearray(v, "UTF-8"));
#else
add(Bytes.ofString(v, encoding));
#end
}
public #if flash inline #end function addInt32(v:Int) {
#if flash
b.writeUnsignedInt(v);
#else
addByte(v & 0xFF);
addByte((v >> 8) & 0xFF);
addByte((v >> 16) & 0xFF);
addByte(v >>> 24);
#end
}
public #if flash inline #end function addInt64(v:haxe.Int64) {
addInt32(v.low);
addInt32(v.high);
}
public inline function addFloat(v:Float) {
#if flash
b.writeFloat(v);
#else
addInt32(FPHelper.floatToI32(v));
#end
}
public inline function addDouble(v:Float) {
#if flash
b.writeDouble(v);
#else
addInt64(FPHelper.doubleToI64(v));
#end
}
public inline function addBytes(src:Bytes, pos:Int, len:Int) {
#if !neko
if (pos < 0 || len < 0 || pos + len > src.length)
throw Error.OutsideBounds;
#end
#if neko
try
untyped StringBuf.__add_sub(b, src.getData(), pos, len)
catch (e:Dynamic)
throw Error.OutsideBounds;
#elseif flash
if (len > 0)
b.writeBytes(src.getData(), pos, len);
#elseif cs
b.Write(src.getData(), pos, len);
#elseif java
b.write(src.getData(), pos, len);
#elseif js
var b1 = b;
var b2 = @:privateAccess src.b;
for (i in pos...pos + len)
b.push(b2[i]);
#elseif python
b.extend(python.Syntax.code("{0}[{1}:{2}]", src.getData(), pos, pos + len));
#else
var b1 = b;
var b2 = src.getData();
for (i in pos...pos + len)
b.push(b2[i]);
#end
}
/**
Returns either a copy or a reference of the current bytes.
Once called, the buffer should no longer be used.
**/
public function getBytes():Bytes
untyped {
#if neko
var str = StringBuf.__to_string(b);
var bytes = new Bytes(__dollar__ssize(str), str);
#elseif flash
var bytes = new Bytes(b.length, b);
b.position = 0;
#elseif cs
var buf = b.GetBuffer();
var bytes = new Bytes(cast b.Length, buf);
#elseif java
var buf = b.toByteArray();
var bytes = new Bytes(buf.length, buf);
#elseif python
var bytes = new Bytes(b.length, b);
#elseif js
var bytes = new Bytes(new js.lib.Uint8Array(b).buffer);
#else
var bytes = new Bytes(b.length, b);
#end
b = null;
return bytes;
}
}

View File

@ -0,0 +1,70 @@
/*
* 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 haxe.io;
#if neko
typedef BytesData = neko.NativeString;
#elseif flash
typedef BytesData = flash.utils.ByteArray;
#elseif cpp
typedef BytesData = Array<cpp.UInt8>;
#elseif java
typedef BytesData = java.NativeArray<java.StdTypes.Int8>;
#elseif cs
typedef BytesData = cs.NativeArray<cs.StdTypes.UInt8>;
#elseif python
typedef BytesData = python.Bytearray;
#elseif js
typedef BytesData = js.lib.ArrayBuffer;
#elseif hl
class BytesDataImpl {
public var bytes:hl.Bytes;
public var length:Int;
public function new(b, length) {
this.bytes = b;
this.length = length;
}
}
@:forward(bytes, length)
abstract BytesDataAbstract(BytesDataImpl) {
public inline function new(b, length) {
this = new BytesDataImpl(b, length);
}
@:arrayAccess inline function get(i:Int)
return this.bytes[i];
@:arrayAccess inline function set(i:Int, v:Int)
return this.bytes[i] = v;
@:to inline function toBytes():hl.Bytes {
return this == null ? null : this.bytes;
}
}
typedef BytesData = BytesDataAbstract;
#else
typedef BytesData = Array<Int>;
#end

View File

@ -0,0 +1,217 @@
/*
* 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 haxe.io;
class BytesInput extends Input {
var b:#if js js.lib.Uint8Array #elseif hl hl.Bytes #else BytesData #end;
#if !flash
var pos:Int;
var len:Int;
var totlen:Int;
#end
/** The current position in the stream in bytes. */
public var position(get, set):Int;
/** The length of the stream in bytes. */
public var length(get, never):Int;
public function new(b:Bytes, ?pos:Int, ?len:Int) {
if (pos == null)
pos = 0;
if (len == null)
len = b.length - pos;
if (pos < 0 || len < 0 || pos + len > b.length)
throw Error.OutsideBounds;
#if flash
var ba = b.getData();
ba.position = pos;
if (len != ba.bytesAvailable) {
// truncate
this.b = new flash.utils.ByteArray();
ba.readBytes(this.b, 0, len);
} else
this.b = ba;
this.b.endian = flash.utils.Endian.LITTLE_ENDIAN;
#else
this.b = #if (js || hl) @:privateAccess b.b #else b.getData() #end;
this.pos = pos;
this.len = len;
this.totlen = len;
#end
#if python
bigEndian = false;
#end
}
inline function get_position():Int {
#if flash
return b.position;
#else
return pos;
#end
}
inline function get_length():Int {
#if flash
return b.length;
#else
return totlen;
#end
}
function set_position(p:Int):Int {
if (p < 0)
p = 0;
else if (p > length)
p = length;
#if flash
return b.position = p;
#else
len = totlen - p;
return pos = p;
#end
}
public override function readByte():Int {
#if flash
return try b.readUnsignedByte() catch (e:Dynamic) throw new Eof();
#else
if (this.len == 0)
throw new Eof();
len--;
#if neko
return untyped __dollar__sget(b, pos++);
#elseif cpp
return untyped b[pos++];
#elseif java
return untyped b[pos++] & 0xFF;
#elseif python // dodge https://github.com/HaxeFoundation/haxe/issues/5080
var b = b[pos];
pos++;
return b;
#else
return b[pos++];
#end
#end
}
public override function readBytes(buf:Bytes, pos:Int, len:Int):Int {
#if !neko
if (pos < 0 || len < 0 || pos + len > buf.length)
throw Error.OutsideBounds;
#end
#if flash
var avail:Int = b.bytesAvailable;
if (len > avail && avail > 0)
len = avail;
try
b.readBytes(buf.getData(), pos, len)
catch (e:Dynamic)
throw new Eof();
#elseif java
var avail:Int = this.len;
if (len > avail)
len = avail;
if (len == 0)
throw new Eof();
java.lang.System.arraycopy(this.b, this.pos, buf.getData(), pos, len);
this.pos += len;
this.len -= len;
#elseif cs
var avail:Int = this.len;
if (len > avail)
len = avail;
if (len == 0)
throw new Eof();
cs.system.Array.Copy(this.b, this.pos, buf.getData(), pos, len);
this.pos += len;
this.len -= len;
#else
if (this.len == 0 && len > 0)
throw new Eof();
if (this.len < len)
len = this.len;
#if neko
try
untyped __dollar__sblit(buf.getData(), pos, b, this.pos, len)
catch (e:Dynamic)
throw Error.OutsideBounds;
#elseif hl
@:privateAccess buf.b.blit(pos, b, this.pos, len);
#else
var b1 = b;
var b2 = #if js @:privateAccess buf.b #else buf.getData() #end;
for (i in 0...len)
b2[pos + i] = b1[this.pos + i];
#end
this.pos += len;
this.len -= len;
#end
return len;
}
#if flash
@:dox(hide)
override function set_bigEndian(e) {
bigEndian = e;
b.endian = e ? flash.utils.Endian.BIG_ENDIAN : flash.utils.Endian.LITTLE_ENDIAN;
return e;
}
@:dox(hide)
override function readFloat() {
return try b.readFloat() catch (e:Dynamic) throw new Eof();
}
@:dox(hide)
override function readDouble() {
return try b.readDouble() catch (e:Dynamic) throw new Eof();
}
@:dox(hide)
override function readInt8() {
return try b.readByte() catch (e:Dynamic) throw new Eof();
}
@:dox(hide)
override function readInt16() {
return try b.readShort() catch (e:Dynamic) throw new Eof();
}
@:dox(hide)
override function readUInt16():Int {
return try b.readUnsignedShort() catch (e:Dynamic) throw new Eof();
}
@:dox(hide)
override function readInt32():Int {
return try b.readInt() catch (e:Dynamic) throw new Eof();
}
@:dox(hide)
override function readString(len:Int, ?encoding:Encoding) {
return try encoding == RawNative ? b.readMultiByte(len, "unicode") : b.readUTFBytes(len) catch (e:Dynamic) throw new Eof();
}
#end
}

View File

@ -0,0 +1,146 @@
/*
* 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 haxe.io;
class BytesOutput extends Output {
#if flash
var b:flash.utils.ByteArray;
#else
var b:BytesBuffer;
#end
/** The length of the stream in bytes. **/
public var length(get, never):Int;
public function new() {
#if flash
b = new flash.utils.ByteArray();
b.endian = flash.utils.Endian.LITTLE_ENDIAN;
#else
b = new BytesBuffer();
#end
#if python
bigEndian = false;
#end
}
inline function get_length():Int {
return b.length;
}
override function writeByte(c) {
#if flash
b.writeByte(c);
#else
b.addByte(c);
#end
}
override function writeBytes(buf:Bytes, pos, len):Int {
#if flash
if (pos < 0 || len < 0 || pos + len > buf.length)
throw Error.OutsideBounds;
b.writeBytes(buf.getData(), pos, len);
#else
b.addBytes(buf, pos, len);
#end
return len;
}
#if flash
// optimized operations
@:dox(hide)
override function set_bigEndian(e) {
bigEndian = e;
b.endian = e ? flash.utils.Endian.BIG_ENDIAN : flash.utils.Endian.LITTLE_ENDIAN;
return e;
}
@:dox(hide)
override function writeFloat(f:Float) {
b.writeFloat(f);
}
@:dox(hide)
override function writeDouble(f:Float) {
b.writeDouble(f);
}
@:dox(hide)
override function writeInt8(x:Int) {
if (x < -0x80 || x >= 0x80)
throw Error.Overflow;
b.writeByte(x);
}
@:dox(hide)
override function writeInt16(x:Int) {
if (x < -0x8000 || x >= 0x8000)
throw Error.Overflow;
b.writeShort(x);
}
@:dox(hide)
override function writeUInt16(x:Int) {
if (x < 0 || x >= 0x10000)
throw Error.Overflow;
b.writeShort(x);
}
@:dox(hide)
override function writeInt32(x:Int) {
b.writeInt(x);
}
@:dox(hide)
override function prepare(size:Int) {
if (size > 0)
b[size - 1] = b[size - 1];
}
@:dox(hide)
override function writeString(s:String, ?encoding:Encoding) {
if (encoding == RawNative)
b.writeMultiByte(s, "unicode");
else
b.writeUTFBytes(s);
}
#end
/**
Returns the `Bytes` of this output.
This function should not be called more than once on a given
`BytesOutput` instance.
**/
public function getBytes():Bytes {
#if flash
var bytes = b;
b = null;
return untyped new Bytes(bytes.length, bytes);
#else
return b.getBytes();
#end
}
}

View File

@ -0,0 +1,35 @@
/*
* 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 haxe.io;
/**
String binary encoding supported by Haxe I/O
**/
enum Encoding {
UTF8;
/**
Output the string the way the platform represent it in memory. This is the most efficient but is platform-specific
**/
RawNative;
}

View File

@ -0,0 +1,35 @@
/*
* 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 haxe.io;
/**
This exception is raised when reading while data is no longer available in the `haxe.io.Input`.
**/
class Eof {
public function new() {}
@:ifFeature("haxe.io.Eof.*")
function toString() {
return "Eof";
}
}

View File

@ -0,0 +1,43 @@
/*
* 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 haxe.io;
/**
The possible IO errors that can occur
**/
#if eval
@:keep
#end
enum Error {
/** The IO is set into nonblocking mode and some data cannot be read or written **/
Blocked;
/** An integer value is outside its allowed range **/
Overflow;
/** An operation on Bytes is outside of its valid range **/
OutsideBounds;
/** Other errors **/
Custom(e:Dynamic);
}

View File

@ -0,0 +1,362 @@
/*
* 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 haxe.io;
/**
Helper that converts between floating point and binary representation.
Always works in low-endian encoding.
**/
class FPHelper {
#if neko_v21
// stored in helper
#elseif neko
static var i64tmp = new sys.thread.Tls<Int64>();
#elseif !(java || cs || cpp)
static var i64tmp = Int64.ofInt(0);
static inline var LN2 = 0.6931471805599453; // Math.log(2)
static inline function _i32ToFloat(i:Int):Float {
var sign = 1 - ((i >>> 31) << 1);
var e = (i >> 23) & 0xff;
if (e == 255)
return i & 0x7fffff == 0 ? (sign > 0 ? Math.POSITIVE_INFINITY : Math.NEGATIVE_INFINITY) : Math.NaN;
var m = e == 0 ? (i & 0x7fffff) << 1 : (i & 0x7fffff) | 0x800000;
return sign * m * Math.pow(2, e - 150);
}
static inline function _i64ToDouble(lo:Int, hi:Int):Float {
var sign = 1 - ((hi >>> 31) << 1);
var e = (hi >> 20) & 0x7ff;
if (e == 2047)
return lo == 0 && (hi & 0xFFFFF) == 0 ? (sign > 0 ? Math.POSITIVE_INFINITY : Math.NEGATIVE_INFINITY) : Math.NaN;
var m = 2.220446049250313e-16 * ((hi & 0xFFFFF) * 4294967296. + (lo >>> 31) * 2147483648. + (lo & 0x7FFFFFFF));
m = e == 0 ? m * 2.0 : m + 1.0;
return sign * m * Math.pow(2, e - 1023);
}
static inline function _floatToI32(f:Float):Int {
if (f == 0)
return 0;
var af = f < 0 ? -f : f;
var exp = Math.floor(Math.log(af) / LN2);
if (exp > 127) {
return 0x7F800000;
} else {
if (exp <= -127) {
exp = -127;
af *= 7.1362384635298e+44; // af * 0.5 * 0x800000 / Math.pow(2, -127)
} else {
af = (af / Math.pow(2, exp) - 1.0) * 0x800000;
}
return (f < 0 ? 0x80000000 : 0) | ((exp + 127) << 23) | Math.round(af);
}
}
static inline function _doubleToI64(v:Float):Int64@:privateAccess {
var i64 = i64tmp;
if (v == 0) {
i64.set_low(0);
i64.set_high(0);
} else if (!Math.isFinite(v)) {
i64.set_low(0);
i64.set_high(v > 0 ? 0x7FF00000 : 0xFFF00000);
} else {
var av = v < 0 ? -v : v;
var exp = Math.floor(Math.log(av) / LN2);
if (exp > 1023) {
i64.set_low(0xFFFFFFFF);
i64.set_high(0x7FEFFFFF);
} else {
if (exp <= -1023) {
exp = -1023;
av = av / 2.2250738585072014e-308;
} else {
av = av / Math.pow(2, exp) - 1.0;
}
var sig = Math.fround(av * 4503599627370496.); // 2^52
// Note: If "sig" is outside of the signed Int32 range, the result is unspecified in HL, C#, Java and Neko,
var sig_l = Std.int(sig);
var sig_h = Std.int(sig / 4294967296.0);
i64.set_low(sig_l);
i64.set_high((v < 0 ? 0x80000000 : 0) | ((exp + 1023) << 20) | sig_h);
}
}
return i64;
}
#end
#if neko
#if neko_v21
static var helpers = new sys.thread.Tls<neko.NativeArray<Dynamic>>();
#else
static var helperf = new sys.thread.Tls<neko.NativeString>();
static var helperd = new sys.thread.Tls<neko.NativeString>();
static var _float_of_bytes = neko.Lib.load("std", "float_of_bytes", 2);
static var _double_of_bytes = neko.Lib.load("std", "double_of_bytes", 2);
static var _float_bytes = neko.Lib.load("std", "float_bytes", 2);
static var _double_bytes = neko.Lib.load("std", "double_bytes", 2);
#end
#elseif flash
static var helper = {
var b = new flash.utils.ByteArray();
b.endian = flash.utils.Endian.LITTLE_ENDIAN;
b;
}
#elseif js
static var helper = new js.lib.DataView(new js.lib.ArrayBuffer(8));
#end
#if neko_v21
inline
#end
public static function i32ToFloat(i:Int):Float {
#if neko
#if neko_v21
return untyped $itof(i, false);
#else
var helper = helperf.value;
if (helper == null)
helperf.value = helper = neko.NativeString.alloc(4);
untyped $sset(helper, 0, i & 0xFF);
untyped $sset(helper, 1, (i >> 8) & 0xFF);
untyped $sset(helper, 2, (i >> 16) & 0xFF);
untyped $sset(helper, 3, i >>> 24);
return _float_of_bytes(helper, false);
#end
#elseif cpp
return untyped __global__.__hxcpp_reinterpret_le_int32_as_float32(i);
#elseif cs
var helper = new SingleHelper(0);
if (cs.system.BitConverter.IsLittleEndian) {
helper.i = i;
} else {
helper.i = ((i >>> 24) & 0xFF) | (((i >> 16) & 0xFF) << 8) | (((i >> 8) & 0xFF) << 16) | ((i & 0xFF) << 24);
}
return helper.f;
#elseif java
return java.lang.Float.FloatClass.intBitsToFloat(i);
#elseif flash
var helper = helper;
helper.position = 0;
helper.writeUnsignedInt(i);
helper.position = 0;
return helper.readFloat();
#elseif js
helper.setInt32(0, i, true);
return helper.getFloat32(0, true);
#else
return _i32ToFloat(i);
#end
}
#if neko_v21
inline
#end
public static function floatToI32(f:Float):Int {
#if neko
#if neko_v21
return untyped $ftoi(f, false);
#else
var r = _float_bytes(f, false);
return untyped $sget(r, 0) | ($sget(r, 1) << 8) | ($sget(r, 2) << 16) | ($sget(r, 3) << 24);
#end
#elseif cpp
return untyped __global__.__hxcpp_reinterpret_float32_as_le_int32(f);
#elseif cs
var helper = new SingleHelper(f);
if (cs.system.BitConverter.IsLittleEndian) {
return helper.i;
} else {
var i = helper.i;
return ((i >>> 24) & 0xFF) | (((i >> 16) & 0xFF) << 8) | (((i >> 8) & 0xFF) << 16) | ((i & 0xFF) << 24);
}
#elseif java
return java.lang.Float.FloatClass.floatToRawIntBits(f);
#elseif flash
var helper = helper;
helper.position = 0;
helper.writeFloat(f);
helper.position = 0;
return helper.readUnsignedInt();
#elseif js
helper.setFloat32(0, f, true);
return helper.getInt32(0, true);
#else
return _floatToI32(f);
#end
}
#if neko_v21
inline
#end
public static function i64ToDouble(low:Int, high:Int):Float {
#if neko
#if neko_v21
return untyped $itod(low, high, false);
#else
var helper = helperd.value;
if (helper == null)
helperd.value = helper = neko.NativeString.alloc(8);
untyped $sset(helper, 0, low & 0xFF);
untyped $sset(helper, 1, (low >> 8) & 0xFF);
untyped $sset(helper, 2, (low >> 16) & 0xFF);
untyped $sset(helper, 3, low >>> 24);
untyped $sset(helper, 4, high & 0xFF);
untyped $sset(helper, 5, (high >> 8) & 0xFF);
untyped $sset(helper, 6, (high >> 16) & 0xFF);
untyped $sset(helper, 7, high >>> 24);
return _double_of_bytes(helper, false);
#end
#elseif cpp
return untyped __global__.__hxcpp_reinterpret_le_int32s_as_float64(low, high);
#elseif cs
var helper = new FloatHelper(0);
if (cs.system.BitConverter.IsLittleEndian) {
helper.i = haxe.Int64.make(high, low);
} else {
var i1 = high, i2 = low;
var j2 = ((i1 >>> 24) & 0xFF) | (((i1 >> 16) & 0xFF) << 8) | (((i1 >> 8) & 0xFF) << 16) | ((i1 & 0xFF) << 24);
var j1 = ((i2 >>> 24) & 0xFF) | (((i2 >> 16) & 0xFF) << 8) | (((i2 >> 8) & 0xFF) << 16) | ((i2 & 0xFF) << 24);
helper.i = haxe.Int64.make(j1, j2);
}
return helper.f;
#elseif java
return java.lang.Double.DoubleClass.longBitsToDouble(Int64.make(high, low));
#elseif flash
var helper = helper;
helper.position = 0;
helper.writeUnsignedInt(low);
helper.writeUnsignedInt(high);
helper.position = 0;
return helper.readDouble();
#elseif js
helper.setInt32(0, low, true);
helper.setInt32(4, high, true);
return helper.getFloat64(0, true);
#else
return _i64ToDouble(low, high);
#end
}
/**
Returns an Int64 representing the bytes representation of the double precision IEEE float value.
WARNING : for performance reason, the same Int64 value might be reused every time. Copy its low/high values before calling again.
We still ensure that this is safe to use in a multithread environment
**/
public static function doubleToI64(v:Float):Int64 {
#if neko
#if neko_v21
var helper = helpers.value;
if (helper == null) {
helpers.value = helper = neko.NativeArray.alloc(2);
helper[0] = neko.NativeArray.alloc(2);
helper[1] = haxe.Int64.ofInt(0);
}
var i64:haxe.Int64 = helper[1], int2 = helper[0];
untyped $dtoi(v, int2, false);
@:privateAccess {
i64.set_low(int2[0]);
i64.set_high(int2[1]);
}
return i64;
#else
var r = _double_bytes(v, false), i64 = i64tmp.value;
if (i64 == null)
i64 = i64tmp.value = haxe.Int64.ofInt(0);
@:privateAccess {
i64.set_low(untyped $sget(r, 0) | ($sget(r, 1) << 8) | ($sget(r, 2) << 16) | ($sget(r, 3) << 24));
i64.set_high(untyped $sget(r, 4) | ($sget(r, 5) << 8) | ($sget(r, 6) << 16) | ($sget(r, 7) << 24));
}
return i64;
#end
#elseif cpp
return Int64.make(untyped __global__.__hxcpp_reinterpret_float64_as_le_int32_high(v),
untyped __global__.__hxcpp_reinterpret_float64_as_le_int32_low(v));
#elseif java
return java.lang.Double.DoubleClass.doubleToRawLongBits(v);
#elseif cs
var helper = new FloatHelper(v);
if (cs.system.BitConverter.IsLittleEndian) {
return helper.i;
} else {
var i = helper.i;
var i1 = haxe.Int64.getHigh(i), i2 = haxe.Int64.getLow(i);
var j2 = ((i1 >>> 24) & 0xFF) | (((i1 >> 16) & 0xFF) << 8) | (((i1 >> 8) & 0xFF) << 16) | ((i1 & 0xFF) << 24);
var j1 = ((i2 >>> 24) & 0xFF) | (((i2 >> 16) & 0xFF) << 8) | (((i2 >> 8) & 0xFF) << 16) | ((i2 & 0xFF) << 24);
return haxe.Int64.make(j1, j2);
}
#elseif flash
var helper = helper;
helper.position = 0;
helper.writeDouble(v);
helper.position = 0;
var i64 = i64tmp;
@:privateAccess {
i64.set_low(cast helper.readUnsignedInt());
i64.set_high(cast helper.readUnsignedInt());
}
return i64;
#elseif js
var i64 = i64tmp;
helper.setFloat64(0, v, true);
@:privateAccess {
i64.set_low(helper.getInt32(0, true));
i64.set_high(helper.getInt32(4, true));
}
return i64;
#else
return _doubleToI64(v);
#end
}
}
#if cs
@:meta(System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit))
@:nativeGen @:struct private class SingleHelper {
@:meta(System.Runtime.InteropServices.FieldOffset(0))
public var i:Int;
@:meta(System.Runtime.InteropServices.FieldOffset(0))
public var f:Single;
public function new(f:Single) {
this.i = 0;
this.f = f;
}
}
@:meta(System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit))
@:nativeGen @:struct private class FloatHelper {
@:meta(System.Runtime.InteropServices.FieldOffset(0))
public var i:haxe.Int64;
@:meta(System.Runtime.InteropServices.FieldOffset(0))
public var f:Float;
public function new(f:Float) {
this.i = haxe.Int64.ofInt(0);
this.f = f;
}
}
#end

View File

@ -0,0 +1,87 @@
/*
* 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 haxe.io;
typedef Float32ArrayData = ArrayBufferView.ArrayBufferViewData;
abstract Float32Array(Float32ArrayData) {
public static inline var BYTES_PER_ELEMENT = 4;
public var length(get, never):Int;
public var view(get, never):ArrayBufferView;
public inline function new(elements:Int) {
this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData();
}
inline function get_length() {
return this.byteLength >> 2;
}
public inline function get_view():ArrayBufferView {
return ArrayBufferView.fromData(this);
}
@:arrayAccess public inline function get(index:Int):Float {
return this.bytes.getFloat((index << 2) + this.byteOffset);
}
@:arrayAccess public inline function set(index:Int, value:Float):Float {
if (index >= 0 && index < length) {
this.bytes.setFloat((index << 2) + this.byteOffset, value);
return value;
}
return 0;
}
public inline function sub(begin:Int, ?length:Int):Float32Array {
return fromData(this.sub(begin << 2, length == null ? null : length << 2));
}
public inline function subarray(?begin:Int, ?end:Int):Float32Array {
return fromData(this.subarray(begin == null ? null : begin << 2, end == null ? null : end << 2));
}
public inline function getData():Float32ArrayData {
return this;
}
public static function fromData(d:Float32ArrayData):Float32Array {
return cast d;
}
public static function fromArray(a:Array<Float>, pos = 0, ?length:Int):Float32Array {
if (length == null)
length = a.length - pos;
if (pos < 0 || length < 0 || pos + length > a.length)
throw Error.OutsideBounds;
var i = new Float32Array(a.length);
for (idx in 0...length)
i[idx] = a[idx + pos];
return i;
}
public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):Float32Array {
return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 2 : length) << 2).getData());
}
}

View File

@ -0,0 +1,87 @@
/*
* 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 haxe.io;
typedef Float64ArrayData = ArrayBufferView.ArrayBufferViewData;
abstract Float64Array(Float64ArrayData) {
public static inline var BYTES_PER_ELEMENT = 8;
public var length(get, never):Int;
public var view(get, never):ArrayBufferView;
public inline function new(elements:Int) {
this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData();
}
inline function get_length() {
return this.byteLength >> 3;
}
public inline function get_view():ArrayBufferView {
return ArrayBufferView.fromData(this);
}
@:arrayAccess public inline function get(index:Int):Float {
return this.bytes.getDouble((index << 3) + this.byteOffset);
}
@:arrayAccess public inline function set(index:Int, value:Float):Float {
if (index >= 0 && index < length) {
this.bytes.setDouble((index << 3) + this.byteOffset, value);
return value;
}
return 0;
}
public inline function sub(begin:Int, ?length:Int):Float64Array {
return fromData(this.sub(begin << 3, length == null ? null : length << 3));
}
public inline function subarray(?begin:Int, ?end:Int):Float64Array {
return fromData(this.subarray(begin == null ? null : begin << 3, end == null ? null : end << 3));
}
public inline function getData():Float64ArrayData {
return this;
}
public static function fromData(d:Float64ArrayData):Float64Array {
return cast d;
}
public static function fromArray(a:Array<Float>, pos = 0, ?length:Int):Float64Array {
if (length == null)
length = a.length - pos;
if (pos < 0 || length < 0 || pos + length > a.length)
throw Error.OutsideBounds;
var i = new Float64Array(a.length);
for (idx in 0...length)
i[idx] = a[idx + pos];
return i;
}
public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):Float64Array {
return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 3 : length) << 3).getData());
}
}

View File

@ -0,0 +1,331 @@
/*
* 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 haxe.io;
/**
An Input is an abstract reader. See other classes in the `haxe.io` package
for several possible implementations.
All functions which read data throw `Eof` when the end of the stream
is reached.
**/
class Input {
/**
Endianness (word byte order) used when reading numbers.
If `true`, big-endian is used, otherwise `little-endian` is used.
**/
public var bigEndian(default, set):Bool;
#if cs
private var helper:BytesData;
#elseif java
private var helper:java.nio.ByteBuffer;
#end
/**
Read and return one byte.
**/
public function readByte():Int {
#if cpp
throw new haxe.exceptions.NotImplementedException();
#else
return throw new haxe.exceptions.NotImplementedException();
#end
}
/**
Read `len` bytes and write them into `s` to the position specified by `pos`.
Returns the actual length of read data that can be smaller than `len`.
See `readFullBytes` that tries to read the exact amount of specified bytes.
**/
public function readBytes(s:Bytes, pos:Int, len:Int):Int {
var k = len;
var b = #if (js || hl) @:privateAccess s.b #else s.getData() #end;
if (pos < 0 || len < 0 || pos + len > s.length)
throw Error.OutsideBounds;
try {
while (k > 0) {
#if neko
untyped __dollar__sset(b, pos, readByte());
#elseif php
b.set(pos, readByte());
#elseif cpp
b[pos] = untyped readByte();
#else
b[pos] = cast readByte();
#end
pos++;
k--;
}
} catch (eof:haxe.io.Eof) {}
return len - k;
}
/**
Close the input source.
Behaviour while reading after calling this method is unspecified.
**/
public function close():Void {}
function set_bigEndian(b:Bool):Bool {
bigEndian = b;
return b;
}
/* ------------------ API ------------------ */
/**
Read and return all available data.
The `bufsize` optional argument specifies the size of chunks by
which data is read. Its default value is target-specific.
**/
public function readAll(?bufsize:Int):Bytes {
if (bufsize == null)
#if php
bufsize = 8192; // default value for PHP and max under certain circumstances
#else
bufsize = (1 << 14); // 16 Ko
#end
var buf = Bytes.alloc(bufsize);
var total = new haxe.io.BytesBuffer();
try {
while (true) {
var len = readBytes(buf, 0, bufsize);
if (len == 0)
throw Error.Blocked;
total.addBytes(buf, 0, len);
}
} catch (e:Eof) {}
return total.getBytes();
}
/**
Read `len` bytes and write them into `s` to the position specified by `pos`.
Unlike `readBytes`, this method tries to read the exact `len` amount of bytes.
**/
public function readFullBytes(s:Bytes, pos:Int, len:Int):Void {
while (len > 0) {
var k = readBytes(s, pos, len);
if (k == 0)
throw Error.Blocked;
pos += k;
len -= k;
}
}
/**
Read and return `nbytes` bytes.
**/
public function read(nbytes:Int):Bytes {
var s = Bytes.alloc(nbytes);
var p = 0;
while (nbytes > 0) {
var k = readBytes(s, p, nbytes);
if (k == 0)
throw Error.Blocked;
p += k;
nbytes -= k;
}
return s;
}
/**
Read a string until a character code specified by `end` is occurred.
The final character is not included in the resulting string.
**/
public function readUntil(end:Int):String {
var buf = new BytesBuffer();
var last:Int;
while ((last = readByte()) != end)
buf.addByte(last);
return buf.getBytes().toString();
}
/**
Read a line of text separated by CR and/or LF bytes.
The CR/LF characters are not included in the resulting string.
**/
public function readLine():String {
var buf = new BytesBuffer();
var last:Int;
var s;
try {
while ((last = readByte()) != 10)
buf.addByte(last);
s = buf.getBytes().toString();
if (s.charCodeAt(s.length - 1) == 13)
s = s.substr(0, -1);
} catch (e:Eof) {
s = buf.getBytes().toString();
if (s.length == 0)
#if neko neko.Lib.rethrow #else throw #end (e);
}
return s;
}
/**
Read a 32-bit floating point number.
Endianness is specified by the `bigEndian` property.
**/
public function readFloat():Float {
return FPHelper.i32ToFloat(readInt32());
}
/**
Read a 64-bit double-precision floating point number.
Endianness is specified by the `bigEndian` property.
**/
public function readDouble():Float {
var i1 = readInt32();
var i2 = readInt32();
return bigEndian ? FPHelper.i64ToDouble(i2, i1) : FPHelper.i64ToDouble(i1, i2);
}
/**
Read a 8-bit signed integer.
**/
public function readInt8():Int {
var n = readByte();
if (n >= 128)
return n - 256;
return n;
}
/**
Read a 16-bit signed integer.
Endianness is specified by the `bigEndian` property.
**/
public function readInt16():Int {
var ch1 = readByte();
var ch2 = readByte();
var n = bigEndian ? ch2 | (ch1 << 8) : ch1 | (ch2 << 8);
if (n & 0x8000 != 0)
return n - 0x10000;
return n;
}
/**
Read a 16-bit unsigned integer.
Endianness is specified by the `bigEndian` property.
**/
public function readUInt16():Int {
var ch1 = readByte();
var ch2 = readByte();
return bigEndian ? ch2 | (ch1 << 8) : ch1 | (ch2 << 8);
}
/**
Read a 24-bit signed integer.
Endianness is specified by the `bigEndian` property.
**/
public function readInt24():Int {
var ch1 = readByte();
var ch2 = readByte();
var ch3 = readByte();
var n = bigEndian ? ch3 | (ch2 << 8) | (ch1 << 16) : ch1 | (ch2 << 8) | (ch3 << 16);
if (n & 0x800000 != 0)
return n - 0x1000000;
return n;
}
/**
Read a 24-bit unsigned integer.
Endianness is specified by the `bigEndian` property.
**/
public function readUInt24():Int {
var ch1 = readByte();
var ch2 = readByte();
var ch3 = readByte();
return bigEndian ? ch3 | (ch2 << 8) | (ch1 << 16) : ch1 | (ch2 << 8) | (ch3 << 16);
}
/**
Read a 32-bit signed integer.
Endianness is specified by the `bigEndian` property.
**/
public function readInt32():Int {
var ch1 = readByte();
var ch2 = readByte();
var ch3 = readByte();
var ch4 = readByte();
#if (php || python)
// php will overflow integers. Convert them back to signed 32-bit ints.
var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
if (n & 0x80000000 != 0)
return (n | 0x80000000);
else
return n;
#elseif lua
var n = bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
return lua.Boot.clampInt32(n);
#else
return bigEndian ? ch4 | (ch3 << 8) | (ch2 << 16) | (ch1 << 24) : ch1 | (ch2 << 8) | (ch3 << 16) | (ch4 << 24);
#end
}
/**
Read and `len` bytes as a string.
**/
public function readString(len:Int, ?encoding:Encoding):String {
var b = Bytes.alloc(len);
readFullBytes(b, 0, len);
#if neko
return neko.Lib.stringReference(b);
#else
return b.getString(0, len, encoding);
#end
}
#if neko
static var _float_of_bytes = neko.Lib.load("std", "float_of_bytes", 2);
static var _double_of_bytes = neko.Lib.load("std", "double_of_bytes", 2);
static function __init__()
untyped {
Input.prototype.bigEndian = false;
}
#end
#if (flash || js || python)
function getDoubleSig(bytes:Array<Int>) {
return (((bytes[1] & 0xF) << 16) | (bytes[2] << 8) | bytes[3]) * 4294967296.
+ (bytes[4] >> 7) * 2147483648
+ (((bytes[4] & 0x7F) << 24) | (bytes[5] << 16) | (bytes[6] << 8) | bytes[7]);
}
#end
}

View File

@ -0,0 +1,87 @@
/*
* 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 haxe.io;
typedef Int32ArrayData = ArrayBufferView.ArrayBufferViewData;
abstract Int32Array(Int32ArrayData) {
public static inline var BYTES_PER_ELEMENT = 4;
public var length(get, never):Int;
public var view(get, never):ArrayBufferView;
public inline function new(elements:Int) {
this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData();
}
inline function get_length() {
return this.byteLength >> 2;
}
public inline function get_view():ArrayBufferView {
return ArrayBufferView.fromData(this);
}
@:arrayAccess public inline function get(index:Int):Int {
return this.bytes.getInt32((index << 2) + this.byteOffset);
}
@:arrayAccess public inline function set(index:Int, value:Int):Int {
if (index >= 0 && index < length) {
this.bytes.setInt32((index << 2) + this.byteOffset, value);
return value;
}
return 0;
}
public inline function sub(begin:Int, ?length:Int):Int32Array {
return fromData(this.sub(begin << 2, length == null ? null : length << 2));
}
public inline function subarray(?begin:Int, ?end:Int):Int32Array {
return fromData(this.subarray(begin == null ? null : begin << 2, end == null ? null : end << 2));
}
public inline function getData():Int32ArrayData {
return this;
}
public static function fromData(d:Int32ArrayData):Int32Array {
return cast d;
}
public static function fromArray(a:Array<Int>, pos = 0, ?length:Int):Int32Array {
if (length == null)
length = a.length - pos;
if (pos < 0 || length < 0 || pos + length > a.length)
throw Error.OutsideBounds;
var i = new Int32Array(a.length);
for (idx in 0...length)
i[idx] = a[idx + pos];
return i;
}
public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):Int32Array {
return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 2 : length) << 2).getData());
}
}

View File

@ -0,0 +1,321 @@
package haxe.io;
/**
HTML MimeType Enum
@see http://www.sitepoint.com/web-foundations/mime-types-complete-list/
**/
enum abstract Mime(String) from String to String {
var XWorldX3dmf = 'x-world/x-3dmf';
var ApplicationOctetStream = 'application/octet-stream';
var ApplicationXAuthorwareBin = 'application/x-authorware-bin';
var ApplicationXAuthorwareMap = 'application/x-authorware-map';
var ApplicationXAuthorwareSeg = 'application/x-authorware-seg';
var TextVndAbc = 'text/vnd.abc';
var TextHtml = 'text/html';
var VideoAnimaflex = 'video/animaflex';
var ApplicationPostscript = 'application/postscript';
var AudioAiff = 'audio/aiff';
var AudioXAiff = 'audio/x-aiff';
var ApplicationXAim = 'application/x-aim';
var TextXAudiosoftIntra = 'text/x-audiosoft-intra';
var ApplicationXNaviAnimation = 'application/x-navi-animation';
var ApplicationXNokia9000CommunicatorAddOnSoftware = 'application/x-nokia-9000-communicator-add-on-software';
var ApplicationMime = 'application/mime';
var ApplicationArj = 'application/arj';
var ImageXJg = 'image/x-jg';
var VideoXMsAsf = 'video/x-ms-asf';
var TextXAsm = 'text/x-asm';
var TextAsp = 'text/asp';
var ApplicationXMplayer2 = 'application/x-mplayer2';
var AudioBasic = 'audio/basic';
var ApplicationXTroffMsvideo = 'application/x-troff-msvideo';
var VideoAvi = 'video/avi';
var VideoMsvideo = 'video/msvideo';
var VideoXMsvideo = 'video/x-msvideo';
var VideoAvsVideo = 'video/avs-video';
var ApplicationXBcpio = 'application/x-bcpio';
var ApplicationMacBinary = 'application/mac-binary';
var ApplicationMacbinary = 'application/macbinary';
var ApplicationXBinary = 'application/x-binary';
var ApplicationXMacbinary = 'application/x-macbinary';
var ImageBmp = 'image/bmp';
var ImageXWindowsBmp = 'image/x-windows-bmp';
var ApplicationBook = 'application/book';
var ApplicationXBzip2 = 'application/x-bzip2';
var ApplicationXBsh = 'application/x-bsh';
var ApplicationXBzip = 'application/x-bzip';
var TextPlain = 'text/plain';
var TextXC = 'text/x-c';
var ApplicationVndMsPkiSeccat = 'application/vnd.ms-pki.seccat';
var ApplicationClariscad = 'application/clariscad';
var ApplicationXCocoa = 'application/x-cocoa';
var ApplicationCdf = 'application/cdf';
var ApplicationXCdf = 'application/x-cdf';
var ApplicationXNetcdf = 'application/x-netcdf';
var ApplicationPkixCert = 'application/pkix-cert';
var ApplicationXX509CaCert = 'application/x-x509-ca-cert';
var ApplicationXChat = 'application/x-chat';
var ApplicationJava = 'application/java';
var ApplicationJavaByteCode = 'application/java-byte-code';
var ApplicationXJavaClass = 'application/x-java-class';
var ApplicationXCpio = 'application/x-cpio';
var ApplicationMacCompactpro = 'application/mac-compactpro';
var ApplicationPkcsCrl = 'application/pkcs-crl';
var ApplicationXCsh = 'application/x-csh';
var TextCss = 'text/css';
var ApplicationXDirector = 'application/x-director';
var ApplicationXDeepv = 'application/x-deepv';
var VideoXDv = 'video/x-dv';
var VideoDl = 'video/dl';
var ApplicationMsword = 'application/msword';
var ApplicationCommonground = 'application/commonground';
var ApplicationDrafting = 'application/drafting';
var ApplicationXDvi = 'application/x-dvi';
var DrawingXDwf = 'drawing/x-dwf (old)';
var ApplicationAcad = 'application/acad';
var ApplicationDxf = 'application/dxf';
var TextXScriptElisp = 'text/x-script.elisp';
var ApplicationXBytecodeElisp = 'application/x-bytecode.elisp (compiled elisp)';
var ApplicationXEnvoy = 'application/x-envoy';
var ApplicationXEsrehber = 'application/x-esrehber';
var TextXSetext = 'text/x-setext';
var ApplicationEnvoy = 'application/envoy';
var TextXFortran = 'text/x-fortran';
var ApplicationVndFdf = 'application/vnd.fdf';
var ImageFif = 'image/fif';
var VideoFli = 'video/fli';
var ImageFlorian = 'image/florian';
var TextVndFmiFlexstor = 'text/vnd.fmi.flexstor';
var VideoXAtomic3dFeature = 'video/x-atomic3d-feature';
var ImageVndFpx = 'image/vnd.fpx';
var ApplicationFreeloader = 'application/freeloader';
var AudioMake = 'audio/make';
var ImageG3fax = 'image/g3fax';
var ImageGif = 'image/gif';
var VideoGl = 'video/gl';
var AudioXGsm = 'audio/x-gsm';
var ApplicationXGsp = 'application/x-gsp';
var ApplicationXGss = 'application/x-gss';
var ApplicationXGtar = 'application/x-gtar';
var ApplicationXCompressed = 'application/x-compressed';
var ApplicationXGzip = 'application/x-gzip';
var ApplicationXHdf = 'application/x-hdf';
var ApplicationXHelpfile = 'application/x-helpfile';
var TextXScript = 'text/x-script';
var ApplicationHlp = 'application/hlp';
var ApplicationVndHpHpgl = 'application/vnd.hp-hpgl';
var ApplicationBinhex = 'application/binhex';
var ApplicationHta = 'application/hta';
var TextXComponent = 'text/x-component';
var TextWebviewhtml = 'text/webviewhtml';
var XConferenceXCooltalk = 'x-conference/x-cooltalk';
var ImageXIcon = 'image/x-icon';
var ImageIef = 'image/ief';
var ApplicationIges = 'application/iges';
var ApplicationXIma = 'application/x-ima';
var ApplicationXHttpdImap = 'application/x-httpd-imap';
var ApplicationInf = 'application/inf';
var ApplicationXInternettSignup = 'application/x-internett-signup';
var ApplicationXIp2 = 'application/x-ip2';
var VideoXIsvideo = 'video/x-isvideo';
var AudioIt = 'audio/it';
var ApplicationXInventor = 'application/x-inventor';
var IWorldIVrml = 'i-world/i-vrml';
var ApplicationXLivescreen = 'application/x-livescreen';
var AudioXJam = 'audio/x-jam';
var ApplicationXJavaCommerce = 'application/x-java-commerce';
var ImageJpeg = 'image/jpeg';
var ImageXJps = 'image/x-jps';
var TextJavascript = 'text/javascript';
var ApplicationJson = 'application/json';
var ApplicationJavascript = 'application/javascript';
var ImageJutvision = 'image/jutvision';
var AudioMidi = 'audio/midi';
var ApplicationXKsh = 'application/x-ksh';
var AudioNspaudio = 'audio/nspaudio';
var AudioXLiveaudio = 'audio/x-liveaudio';
var ApplicationXLatex = 'application/x-latex';
var ApplicationXLisp = 'application/x-lisp';
var TextXLaAsf = 'text/x-la-asf';
var ApplicationLzx = 'application/lzx';
var VideoMpeg = 'video/mpeg';
var AudioMpeg = 'audio/mpeg';
var AudioXMpequrl = 'audio/x-mpequrl';
var ApplicationXTroffMan = 'application/x-troff-man';
var ApplicationXNavimap = 'application/x-navimap';
var ApplicationMbedlet = 'application/mbedlet';
var ApplicationXMagicCapPackage10 = 'application/x-magic-cap-package-1.0';
var ApplicationMcad = 'application/mcad';
var ImageVasa = 'image/vasa';
var ApplicationNetmc = 'application/netmc';
var ApplicationXTroffMe = 'application/x-troff-me';
var MessageRfc822 = 'message/rfc822';
var ApplicationXMif = 'application/x-mif';
var WwwMime = 'www/mime';
var AudioXVndAudioexplosionMjuicemediafile = 'audio/x-vnd.audioexplosion.mjuicemediafile';
var VideoXMotionJpeg = 'video/x-motion-jpeg';
var ApplicationBase64 = 'application/base64';
var AudioMod = 'audio/mod';
var VideoQuicktime = 'video/quicktime';
var VideoXSgiMovie = 'video/x-sgi-movie';
var AudioMpeg3 = 'audio/mpeg3';
var ApplicationXProject = 'application/x-project';
var ApplicationVndMsProject = 'application/vnd.ms-project';
var ApplicationMarc = 'application/marc';
var ApplicationXTroffMs = 'application/x-troff-ms';
var ApplicationXVndAudioexplosionMzz = 'application/x-vnd.audioexplosion.mzz';
var ImageNaplps = 'image/naplps';
var ApplicationVndNokiaConfigurationMessage = 'application/vnd.nokia.configuration-message';
var ImageXNiff = 'image/x-niff';
var ApplicationXMixTransfer = 'application/x-mix-transfer';
var ApplicationXConference = 'application/x-conference';
var ApplicationXNavidoc = 'application/x-navidoc';
var ApplicationOda = 'application/oda';
var ApplicationXOmc = 'application/x-omc';
var ApplicationXOmcdatamaker = 'application/x-omcdatamaker';
var ApplicationXOmcregerator = 'application/x-omcregerator';
var TextXPascal = 'text/x-pascal';
var ApplicationPkcs10 = 'application/pkcs10';
var ApplicationPkcs12 = 'application/pkcs-12';
var ApplicationXPkcs7Signature = 'application/x-pkcs7-signature';
var ApplicationPkcs7Mime = 'application/pkcs7-mime';
var ApplicationXPkcs7Certreqresp = 'application/x-pkcs7-certreqresp';
var ApplicationPkcs7Signature = 'application/pkcs7-signature';
var ApplicationPro_eng = 'application/pro_eng';
var TextPascal = 'text/pascal';
var ImageXPortableBitmap = 'image/x-portable-bitmap';
var ApplicationVndHpPcl = 'application/vnd.hp-pcl';
var ImageXPict = 'image/x-pict';
var ImageXPcx = 'image/x-pcx';
var ChemicalXPdb = 'chemical/x-pdb';
var ApplicationPdf = 'application/pdf';
var ImageXPortableGraymap = 'image/x-portable-graymap';
var ImagePict = 'image/pict';
var ApplicationXNewtonCompatiblePkg = 'application/x-newton-compatible-pkg';
var ApplicationVndMsPkiPko = 'application/vnd.ms-pki.pko';
var ApplicationXPixclscript = 'application/x-pixclscript';
var ImageXXpixmap = 'image/x-xpixmap';
var ApplicationXPagemaker = 'application/x-pagemaker';
var ImagePng = 'image/png';
var ApplicationXPortableAnymap = 'application/x-portable-anymap';
var ApplicationMspowerpoint = 'application/mspowerpoint';
var ModelXPov = 'model/x-pov';
var ApplicationVndMsPowerpoint = 'application/vnd.ms-powerpoint';
var ImageXPortablePixmap = 'image/x-portable-pixmap';
var ApplicationXFreelance = 'application/x-freelance';
var PaleovuXPv = 'paleovu/x-pv';
var TextXScriptPhyton = 'text/x-script.phyton';
var ApplicationXBytecodePython = 'application/x-bytecode.python';
var AudioVndQcelp = 'audio/vnd.qcelp';
var ImageXQuicktime = 'image/x-quicktime';
var VideoXQtc = 'video/x-qtc';
var AudioXPnRealaudio = 'audio/x-pn-realaudio';
var ApplicationXCmuRaster = 'application/x-cmu-raster';
var ImageCmuRaster = 'image/cmu-raster';
var TextXScriptRexx = 'text/x-script.rexx';
var ImageVndRnRealflash = 'image/vnd.rn-realflash';
var ImageXRgb = 'image/x-rgb';
var ApplicationVndRnRealmedia = 'application/vnd.rn-realmedia';
var AudioMid = 'audio/mid';
var ApplicationRingingTones = 'application/ringing-tones';
var ApplicationVndRnRealplayer = 'application/vnd.rn-realplayer';
var ApplicationXTroff = 'application/x-troff';
var ImageVndRnRealpix = 'image/vnd.rn-realpix';
var AudioXPnRealaudioPlugin = 'audio/x-pn-realaudio-plugin';
var TextRichtext = 'text/richtext';
var ApplicationRtf = 'application/rtf';
var VideoVndRnRealvideo = 'video/vnd.rn-realvideo';
var AudioS3m = 'audio/s3m';
var ApplicationXTbook = 'application/x-tbook';
var ApplicationXLotusscreencam = 'application/x-lotusscreencam';
var ApplicationSdp = 'application/sdp';
var ApplicationSounder = 'application/sounder';
var ApplicationSea = 'application/sea';
var ApplicationSet = 'application/set';
var AudioXPsid = 'audio/x-psid';
var ApplicationXSit = 'application/x-sit';
var ApplicationXKoan = 'application/x-koan';
var ApplicationXSeelogo = 'application/x-seelogo';
var ApplicationSmil = 'application/smil';
var ApplicationSolids = 'application/solids';
var ApplicationXPkcs7Certificates = 'application/x-pkcs7-certificates';
var ApplicationFuturesplash = 'application/futuresplash';
var ApplicationXSprite = 'application/x-sprite';
var ApplicationXWaisSource = 'application/x-wais-source';
var TextXServerParsedHtml = 'text/x-server-parsed-html';
var ApplicationStreamingmedia = 'application/streamingmedia';
var ApplicationVndMsPkiCertstore = 'application/vnd.ms-pki.certstore';
var ApplicationStep = 'application/step';
var ApplicationSla = 'application/sla';
var ApplicationXSv4cpio = 'application/x-sv4cpio';
var ApplicationXSv4crc = 'application/x-sv4crc';
var ImageVndDwg = 'image/vnd.dwg';
var ApplicationXWorld = 'application/x-world';
var ApplicationXShockwaveFlash = 'application/x-shockwave-flash';
var TextXSpeech = 'text/x-speech';
var ApplicationXTar = 'application/x-tar';
var ApplicationToolbook = 'application/toolbook';
var ApplicationXTcl = 'application/x-tcl';
var TextXScriptTcsh = 'text/x-script.tcsh';
var ApplicationXTex = 'application/x-tex';
var ApplicationXTexinfo = 'application/x-texinfo';
var ApplicationGnutar = 'application/gnutar';
var ImageTiff = 'image/tiff';
var AudioTspAudio = 'audio/tsp-audio';
var ApplicationDsptype = 'application/dsptype';
var TextTabSeparatedValues = 'text/tab-separated-values';
var TextXUil = 'text/x-uil';
var TextUriList = 'text/uri-list';
var ApplicationIDeas = 'application/i-deas';
var ApplicationXUstar = 'application/x-ustar';
var TextXUuencode = 'text/x-uuencode';
var ApplicationXCdlink = 'application/x-cdlink';
var TextXVcalendar = 'text/x-vcalendar';
var ApplicationVda = 'application/vda';
var VideoVdo = 'video/vdo';
var ApplicationGroupwise = 'application/groupwise';
var VideoVivo = 'video/vivo';
var ApplicationVocaltecMediaDesc = 'application/vocaltec-media-desc';
var ApplicationVocaltecMediaFile = 'application/vocaltec-media-file';
var AudioVoc = 'audio/voc';
var VideoVosaic = 'video/vosaic';
var AudioVoxware = 'audio/voxware';
var AudioXTwinvqPlugin = 'audio/x-twinvq-plugin';
var AudioXTwinvq = 'audio/x-twinvq';
var ApplicationXVrml = 'application/x-vrml';
var XWorldXVrt = 'x-world/x-vrt';
var ApplicationXVisio = 'application/x-visio';
var ApplicationWordperfect60 = 'application/wordperfect6.0';
var ApplicationWordperfect61 = 'application/wordperfect6.1';
var AudioWav = 'audio/wav';
var ApplicationXQpro = 'application/x-qpro';
var ImageVndWapWbmp = 'image/vnd.wap.wbmp';
var ApplicationVndXara = 'application/vnd.xara';
var ImageWebp = 'image/webp';
var ApplicationX123 = 'application/x-123';
var WindowsMetafile = 'windows/metafile';
var TextVndWapWml = 'text/vnd.wap.wml';
var ApplicationVndWapWmlc = 'application/vnd.wap.wmlc';
var TextVndWapWmlscript = 'text/vnd.wap.wmlscript';
var ApplicationVndWapWmlscriptc = 'application/vnd.wap.wmlscriptc';
var ApplicationWordperfect = 'application/wordperfect';
var ApplicationXLotus = 'application/x-lotus';
var ApplicationMswrite = 'application/mswrite';
var ModelVrml = 'model/vrml';
var TextScriplet = 'text/scriplet';
var ApplicationXWintalk = 'application/x-wintalk';
var ImageXXbitmap = 'image/x-xbitmap';
var VideoXAmtDemorun = 'video/x-amt-demorun';
var XglDrawing = 'xgl/drawing';
var ImageVndXiff = 'image/vnd.xiff';
var ApplicationExcel = 'application/excel';
var AudioXm = 'audio/xm';
var ApplicationXml = 'application/xml';
var XglMovie = 'xgl/movie';
var ApplicationXVndLsXpix = 'application/x-vnd.ls-xpix';
var VideoXAmtShowrun = 'video/x-amt-showrun';
var ImageXXwd = 'image/x-xwd';
var ApplicationXCompress = 'application/x-compress';
var MultipartXZip = 'multipart/x-zip';
var TextXScriptZsh = 'text/x-script.zsh';
}

View File

@ -0,0 +1,293 @@
/*
* 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 haxe.io;
/**
An Output is an abstract write. A specific output implementation will only
have to override the `writeByte` and maybe the `write`, `flush` and `close`
methods. See `File.write` and `String.write` for two ways of creating an
Output.
**/
class Output {
/**
Endianness (word byte order) used when writing numbers.
If `true`, big-endian is used, otherwise `little-endian` is used.
**/
public var bigEndian(default, set):Bool;
#if java
private var helper:java.nio.ByteBuffer;
#end
/**
Write one byte.
**/
public function writeByte(c:Int):Void {
throw new haxe.exceptions.NotImplementedException();
}
/**
Write `len` bytes from `s` starting by position specified by `pos`.
Returns the actual length of written data that can differ from `len`.
See `writeFullBytes` that tries to write the exact amount of specified bytes.
**/
public function writeBytes(s:Bytes, pos:Int, len:Int):Int {
#if !neko
if (pos < 0 || len < 0 || pos + len > s.length)
throw Error.OutsideBounds;
#end
var b = #if js @:privateAccess s.b #else s.getData() #end;
var k = len;
while (k > 0) {
#if neko
writeByte(untyped __dollar__sget(b, pos));
#elseif php
writeByte(b.get(pos));
#elseif cpp
writeByte(untyped b[pos]);
#elseif hl
writeByte(b[pos]);
#else
writeByte(untyped b[pos]);
#end
pos++;
k--;
}
return len;
}
/**
Flush any buffered data.
**/
public function flush() {}
/**
Close the output.
Behaviour while writing after calling this method is unspecified.
**/
public function close() {}
function set_bigEndian(b) {
bigEndian = b;
return b;
}
/* ------------------ API ------------------ */
/**
Write all bytes stored in `s`.
**/
public function write(s:Bytes):Void {
var l = s.length;
var p = 0;
while (l > 0) {
var k = writeBytes(s, p, l);
if (k == 0)
throw Error.Blocked;
p += k;
l -= k;
}
}
/**
Write `len` bytes from `s` starting by position specified by `pos`.
Unlike `writeBytes`, this method tries to write the exact `len` amount of bytes.
**/
public function writeFullBytes(s:Bytes, pos:Int, len:Int) {
while (len > 0) {
var k = writeBytes(s, pos, len);
pos += k;
len -= k;
}
}
/**
Write `x` as 32-bit floating point number.
Endianness is specified by the `bigEndian` property.
**/
public function writeFloat(x:Float) {
writeInt32(FPHelper.floatToI32(x));
}
/**
Write `x` as 64-bit double-precision floating point number.
Endianness is specified by the `bigEndian` property.
**/
public function writeDouble(x:Float) {
var i64 = FPHelper.doubleToI64(x);
if (bigEndian) {
writeInt32(i64.high);
writeInt32(i64.low);
} else {
writeInt32(i64.low);
writeInt32(i64.high);
}
}
/**
Write `x` as 8-bit signed integer.
**/
public function writeInt8(x:Int) {
if (x < -0x80 || x >= 0x80)
throw Error.Overflow;
writeByte(x & 0xFF);
}
/**
Write `x` as 16-bit signed integer.
Endianness is specified by the `bigEndian` property.
**/
public function writeInt16(x:Int) {
if (x < -0x8000 || x >= 0x8000)
throw Error.Overflow;
writeUInt16(x & 0xFFFF);
}
/**
Write `x` as 16-bit unsigned integer.
Endianness is specified by the `bigEndian` property.
**/
public function writeUInt16(x:Int) {
if (x < 0 || x >= 0x10000)
throw Error.Overflow;
if (bigEndian) {
writeByte(x >> 8);
writeByte(x & 0xFF);
} else {
writeByte(x & 0xFF);
writeByte(x >> 8);
}
}
/**
Write `x` as 24-bit signed integer.
Endianness is specified by the `bigEndian` property.
**/
public function writeInt24(x:Int) {
if (x < -0x800000 || x >= 0x800000)
throw Error.Overflow;
writeUInt24(x & 0xFFFFFF);
}
/**
Write `x` as 24-bit unsigned integer.
Endianness is specified by the `bigEndian` property.
**/
public function writeUInt24(x:Int) {
if (x < 0 || x >= 0x1000000)
throw Error.Overflow;
if (bigEndian) {
writeByte(x >> 16);
writeByte((x >> 8) & 0xFF);
writeByte(x & 0xFF);
} else {
writeByte(x & 0xFF);
writeByte((x >> 8) & 0xFF);
writeByte(x >> 16);
}
}
/**
Write `x` as 32-bit signed integer.
Endianness is specified by the `bigEndian` property.
**/
public function writeInt32(x:Int) {
if (bigEndian) {
writeByte(x >>> 24);
writeByte((x >> 16) & 0xFF);
writeByte((x >> 8) & 0xFF);
writeByte(x & 0xFF);
} else {
writeByte(x & 0xFF);
writeByte((x >> 8) & 0xFF);
writeByte((x >> 16) & 0xFF);
writeByte(x >>> 24);
}
}
/**
Inform that we are about to write at least `nbytes` bytes.
The underlying implementation can allocate proper working space depending
on this information, or simply ignore it. This is not a mandatory call
but a tip and is only used in some specific cases.
**/
public function prepare(nbytes:Int) {}
/**
Read all available data from `i` and write it.
The `bufsize` optional argument specifies the size of chunks by
which data is read and written. Its default value is 4096.
**/
public function writeInput(i:Input, ?bufsize:Int) {
if (bufsize == null)
bufsize = 4096;
var buf = Bytes.alloc(bufsize);
try {
while (true) {
var len = i.readBytes(buf, 0, bufsize);
if (len == 0)
throw Error.Blocked;
var p = 0;
while (len > 0) {
var k = writeBytes(buf, p, len);
if (k == 0)
throw Error.Blocked;
p += k;
len -= k;
}
}
} catch (e:Eof) {}
}
/**
Write `s` string.
**/
public function writeString(s:String, ?encoding:Encoding) {
#if neko
var b = untyped new Bytes(s.length, s.__s);
#else
var b = Bytes.ofString(s, encoding);
#end
writeFullBytes(b, 0, b.length);
}
#if neko
static function __init__()
untyped {
Output.prototype.bigEndian = false;
}
#end
}

View File

@ -0,0 +1,333 @@
/*
* 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 haxe.io;
/**
This class provides a convenient way of working with paths. It supports the
common path formats:
- `directory1/directory2/filename.extension`
- `directory1\directory2\filename.extension`
**/
class Path {
/**
The directory.
This is the leading part of the path that is not part of the file name
and the extension.
Does not end with a `/` or `\` separator.
If the path has no directory, the value is `null`.
**/
public var dir:Null<String>;
/**
The file name.
This is the part of the part between the directory and the extension.
If there is no file name, e.g. for `".htaccess"` or `"/dir/"`, the value
is the empty String `""`.
**/
public var file:String;
/**
The file extension.
It is separated from the file name by a dot. This dot is not part of
the extension.
If the path has no extension, the value is `null`.
**/
public var ext:Null<String>;
/**
`true` if the last directory separator is a backslash, `false` otherwise.
**/
public var backslash:Bool;
/**
Creates a new `Path` instance by parsing `path`.
Path information can be retrieved by accessing the `dir`, `file` and `ext`
properties.
**/
public function new(path:String) {
switch (path) {
case "." | "..":
dir = path;
file = "";
return;
}
var c1 = path.lastIndexOf("/");
var c2 = path.lastIndexOf("\\");
if (c1 < c2) {
dir = path.substr(0, c2);
path = path.substr(c2 + 1);
backslash = true;
} else if (c2 < c1) {
dir = path.substr(0, c1);
path = path.substr(c1 + 1);
} else
dir = null;
var cp = path.lastIndexOf(".");
if (cp != -1) {
ext = path.substr(cp + 1);
file = path.substr(0, cp);
} else {
ext = null;
file = path;
}
}
/**
Returns a String representation of `this` path.
If `this.backslash` is `true`, backslash is used as directory separator,
otherwise slash is used. This only affects the separator between
`this.dir` and `this.file`.
If `this.directory` or `this.extension` is `null`, their representation
is the empty String `""`.
**/
public function toString():String {
return (if (dir == null) "" else dir + if (backslash) "\\" else "/") + file + (if (ext == null) "" else "." + ext);
}
/**
Returns the String representation of `path` without the file extension.
If `path` is `null`, the result is unspecified.
**/
public static function withoutExtension(path:String):String {
var s = new Path(path);
s.ext = null;
return s.toString();
}
/**
Returns the String representation of `path` without the directory.
If `path` is `null`, the result is unspecified.
**/
public static function withoutDirectory(path):String {
var s = new Path(path);
s.dir = null;
return s.toString();
}
/**
Returns the directory of `path`.
If the directory is `null`, the empty String `""` is returned.
If `path` is `null`, the result is unspecified.
**/
public static function directory(path):String {
var s = new Path(path);
if (s.dir == null)
return "";
return s.dir;
}
/**
Returns the extension of `path`.
If `path` has no extension, the empty String `""` is returned.
If `path` is `null`, the result is unspecified.
**/
public static function extension(path):String {
var s = new Path(path);
if (s.ext == null)
return "";
return s.ext;
}
/**
Returns a String representation of `path` where the extension is `ext`.
If `path` has no extension, `ext` is added as extension.
If `path` or `ext` are `null`, the result is unspecified.
**/
public static function withExtension(path, ext):String {
var s = new Path(path);
s.ext = ext;
return s.toString();
}
/**
Joins all paths in `paths` together.
If `paths` is empty, the empty String `""` is returned. Otherwise the
paths are joined with a slash between them.
If `paths` is `null`, the result is unspecified.
**/
public static function join(paths:Array<String>):String {
var paths = paths.filter(function(s) return s != null && s != "");
if (paths.length == 0) {
return "";
}
var path = paths[0];
for (i in 1...paths.length) {
path = addTrailingSlash(path);
path += paths[i];
}
return normalize(path);
}
/**
Normalize a given `path` (e.g. turn `'/usr/local/../lib'` into `'/usr/lib'`).
Also replaces backslashes `\` with slashes `/` and afterwards turns
multiple slashes into a single one.
If `path` is `null`, the result is unspecified.
**/
public static function normalize(path:String):String {
var slash = "/";
path = path.split("\\").join(slash);
if (path == slash)
return slash;
var target = [];
for (token in path.split(slash)) {
if (token == '..' && target.length > 0 && target[target.length - 1] != "..") {
target.pop();
} else if (token == '') {
if (target.length > 0 || path.charCodeAt(0) == '/'.code) {
target.push(token);
}
} else if (token != '.') {
target.push(token);
}
}
var tmp = target.join(slash);
var acc = new StringBuf();
var colon = false;
var slashes = false;
#if utf16
for (c in haxe.iterators.StringIteratorUnicode.unicodeIterator(tmp)) {
switch (c) {
#else
for (i in 0...tmp.length) {
switch (StringTools.fastCodeAt(tmp, i)) {
#end
case ":".code:
acc.add(":");
colon = true;
case "/".code if (!colon):
slashes = true;
case var i:
colon = false;
if (slashes) {
acc.add("/");
slashes = false;
}
acc.addChar(i);
}
}
return acc.toString();
}
/**
Adds a trailing slash to `path`, if it does not have one already.
If the last slash in `path` is a backslash, a backslash is appended to
`path`.
If the last slash in `path` is a slash, or if no slash is found, a slash
is appended to `path`. In particular, this applies to the empty String
`""`.
If `path` is `null`, the result is unspecified.
**/
public static function addTrailingSlash(path:String):String {
if (path.length == 0)
return "/";
var c1 = path.lastIndexOf("/");
var c2 = path.lastIndexOf("\\");
return if (c1 < c2) {
if (c2 != path.length - 1)
path + "\\";
else
path;
} else {
if (c1 != path.length - 1)
path + "/";
else
path;
}
}
/**
Removes trailing slashes from `path`.
If `path` does not end with a `/` or `\`, `path` is returned unchanged.
Otherwise the substring of `path` excluding the trailing slashes or
backslashes is returned.
If `path` is `null`, the result is unspecified.
**/
public static function removeTrailingSlashes(path:String):String {
while (true) {
switch (path.charCodeAt(path.length - 1)) {
case '/'.code | '\\'.code:
path = path.substr(0, -1);
case _:
break;
}
}
return path;
}
/**
Returns `true` if the path is an absolute path, and `false` otherwise.
**/
public static function isAbsolute(path:String):Bool {
if (StringTools.startsWith(path, '/'))
return true;
if (path.charAt(1) == ':')
return true;
if (StringTools.startsWith(path, '\\\\'))
return true;
return false;
}
private static function unescape(path:String):String {
var regex = ~/-x([0-9][0-9])/g;
return regex.map(path, function(regex) return String.fromCharCode(Std.parseInt(regex.matched(1))));
}
private static function escape(path:String, allowSlashes:Bool = false):String {
var regex = allowSlashes ? ~/[^A-Za-z0-9_\/\\\.]/g : ~/[^A-Za-z0-9_\.]/g;
return regex.map(path, function(v) return '-x' + v.matched(0).charCodeAt(0));
}
}

View File

@ -0,0 +1,18 @@
package haxe.io;
/**
A scheme consists of a sequence of characters beginning with a letter and followed
by any combination of letters, digits, plus (`+`, period (`.`), or hyphen (`-`).
Although schemes are case-insensitive, the canonical form is lowercase
and documents that specify schemes must do so with lowercase letters.
It is followed by a colon (`:`).
**/
enum abstract Scheme(String) from String to String {
var Http = 'http';
var Https = 'https';
var Ftp = 'ftp';
var MailTo = 'mailto';
var File = 'file';
var Data = 'data';
}

View File

@ -0,0 +1,29 @@
/*
* 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 haxe.io;
class StringInput extends BytesInput {
public function new(s:String) {
super(haxe.io.Bytes.ofString(s));
}
}

View File

@ -0,0 +1,87 @@
/*
* 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 haxe.io;
typedef UInt16ArrayData = ArrayBufferView.ArrayBufferViewData;
abstract UInt16Array(UInt16ArrayData) {
public static inline var BYTES_PER_ELEMENT = 2;
public var length(get, never):Int;
public var view(get, never):ArrayBufferView;
public inline function new(elements:Int) {
this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData();
}
inline function get_length() {
return this.byteLength >> 1;
}
public inline function get_view():ArrayBufferView {
return ArrayBufferView.fromData(this);
}
@:arrayAccess public inline function get(index:Int):Int {
return this.bytes.getUInt16((index << 1) + this.byteOffset);
}
@:arrayAccess public inline function set(index:Int, value:Int):Int {
if (index >= 0 && index < length) {
this.bytes.setUInt16((index << 1) + this.byteOffset, value);
return value;
}
return 0;
}
public inline function sub(begin:Int, ?length:Int):UInt16Array {
return fromData(this.sub(begin << 1, length == null ? null : length << 1));
}
public inline function subarray(?begin:Int, ?end:Int):UInt16Array {
return fromData(this.subarray(begin == null ? null : begin << 1, end == null ? null : end << 1));
}
public inline function getData():UInt16ArrayData {
return this;
}
public static function fromData(d:UInt16ArrayData):UInt16Array {
return cast d;
}
public static function fromArray(a:Array<Int>, pos = 0, ?length:Int):UInt16Array {
if (length == null)
length = a.length - pos;
if (pos < 0 || length < 0 || pos + length > a.length)
throw Error.OutsideBounds;
var i = new UInt16Array(a.length);
for (idx in 0...length)
i[idx] = a[idx + pos];
return i;
}
public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):UInt16Array {
return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 1 : length) << 1).getData());
}
}

View File

@ -0,0 +1,87 @@
/*
* 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 haxe.io;
typedef UInt32ArrayData = ArrayBufferView.ArrayBufferViewData;
abstract UInt32Array(UInt32ArrayData) {
public static inline var BYTES_PER_ELEMENT = 4;
public var length(get, never):Int;
public var view(get, never):ArrayBufferView;
public inline function new(elements:Int) {
this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData();
}
inline function get_length() {
return this.byteLength >> 2;
}
public inline function get_view():ArrayBufferView {
return ArrayBufferView.fromData(this);
}
@:arrayAccess public inline function get(index:Int):UInt {
return this.bytes.getInt32((index << 2) + this.byteOffset);
}
@:arrayAccess public inline function set(index:Int, value:UInt):UInt {
if (index >= 0 && index < length) {
this.bytes.setInt32((index << 2) + this.byteOffset, value);
return value;
}
return 0;
}
public inline function sub(begin:Int, ?length:Int):UInt32Array {
return fromData(this.sub(begin << 2, length == null ? null : length << 2));
}
public inline function subarray(?begin:Int, ?end:Int):UInt32Array {
return fromData(this.subarray(begin == null ? null : begin << 2, end == null ? null : end << 2));
}
public inline function getData():UInt32ArrayData {
return this;
}
public static function fromData(d:UInt32ArrayData):UInt32Array {
return cast d;
}
public static function fromArray(a:Array<UInt>, pos = 0, ?length:Int):UInt32Array {
if (length == null)
length = a.length - pos;
if (pos < 0 || length < 0 || pos + length > a.length)
throw Error.OutsideBounds;
var i = new UInt32Array(a.length);
for (idx in 0...length)
i[idx] = a[idx + pos];
return i;
}
public static function fromBytes(bytes:haxe.io.Bytes, bytePos = 0, ?length:Int):UInt32Array {
return fromData(ArrayBufferView.fromBytes(bytes, bytePos, (length == null ? (bytes.length - bytePos) >> 2 : length) << 2).getData());
}
}

View File

@ -0,0 +1,87 @@
/*
* 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 haxe.io;
typedef UInt8ArrayData = ArrayBufferView.ArrayBufferViewData;
abstract UInt8Array(UInt8ArrayData) {
public static inline var BYTES_PER_ELEMENT = 1;
public var length(get, never):Int;
public var view(get, never):ArrayBufferView;
public inline function new(elements:Int) {
this = new ArrayBufferView(elements * BYTES_PER_ELEMENT).getData();
}
inline function get_length() {
return this.byteLength;
}
public inline function get_view():ArrayBufferView {
return ArrayBufferView.fromData(this);
}
@:arrayAccess public inline function get(index:Int) {
return this.bytes.get(index + this.byteOffset);
}
@:arrayAccess public inline function set(index:Int, value:Int):Int {
if (index >= 0 && index < length) {
this.bytes.set(index + this.byteOffset, value);
return value;
}
return 0;
}
public inline function sub(begin:Int, ?length:Int):UInt8Array {
return fromData(this.sub(begin, length));
}
public inline function subarray(?begin:Int, ?end:Int):UInt8Array {
return fromData(this.subarray(begin, end));
}
public inline function getData():UInt8ArrayData {
return this;
}
public static function fromData(d:UInt8ArrayData):UInt8Array {
return cast d;
}
public static function fromArray(a:Array<Int>, pos = 0, ?length:Int):UInt8Array {
if (length == null)
length = a.length - pos;
if (pos < 0 || length < 0 || pos + length > a.length)
throw Error.OutsideBounds;
var i = new UInt8Array(a.length);
for (idx in 0...length)
i[idx] = a[idx + pos];
return i;
}
public static function fromBytes(bytes:haxe.io.Bytes, bytePos:Int = 0, ?length:Int):UInt8Array {
return fromData(ArrayBufferView.fromBytes(bytes, bytePos, length).getData());
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C)2005-2018 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 haxe.iterators;
/**
This iterator is used only when `Array<T>` is passed to `Iterable<T>`
**/
class ArrayIterator<T> {
final array:Array<T>;
var current:Int = 0;
/**
Create a new `ArrayIterator`.
**/
#if !hl inline #end
public function new(array:Array<T>) {
this.array = array;
}
/**
See `Iterator.hasNext`
**/
#if !hl inline #end
public function hasNext() {
return current < array.length;
}
/**
See `Iterator.next`
**/
#if !hl inline #end
public function next() {
return array[current++];
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (C)2005-2018 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 haxe.iterators;
@:ifFeature("anon_read.keyValueIterator", "dynamic_read.keyValueIterator")
class ArrayKeyValueIterator<T> {
var current:Int = 0;
var array:Array<T>;
#if !hl inline #end
public function new(array:Array<T>) {
this.array = array;
}
#if !hl inline #end
public function hasNext():Bool {
return current < array.length;
}
#if !hl inline #end
public function next():{key:Int,value:T} {
return {value:array[current], key:current++};
}
}

View File

@ -0,0 +1,52 @@
/*
* 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 haxe.iterators;
/**
This iterator can be used to iterate over the values of `haxe.DynamicAccess`.
**/
class DynamicAccessIterator<T> {
final access:DynamicAccess<T>;
final keys:Array<String>;
var index:Int;
public inline function new(access:DynamicAccess<T>) {
this.access = access;
this.keys = access.keys();
index = 0;
}
/**
See `Iterator.hasNext`
**/
public inline function hasNext():Bool {
return index < keys.length;
}
/**
See `Iterator.next`
**/
public inline function next():T {
return access[keys[index++]];
}
}

View File

@ -0,0 +1,53 @@
/*
* 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 haxe.iterators;
/**
This Key/Value iterator can be used to iterate over `haxe.DynamicAccess`.
**/
class DynamicAccessKeyValueIterator<T> {
final access:DynamicAccess<T>;
final keys:Array<String>;
var index:Int;
public inline function new(access:DynamicAccess<T>) {
this.access = access;
this.keys = access.keys();
index = 0;
}
/**
See `Iterator.hasNext`
**/
public inline function hasNext():Bool {
return index < keys.length;
}
/**
See `Iterator.next`
**/
public inline function next():{key:String, value:T} {
var key = keys[index++];
return {value: (access[key] : T), key: key};
}
}

View File

@ -0,0 +1,28 @@
package haxe.iterators;
import haxe.ds.HashMap;
class HashMapKeyValueIterator<K:{function hashCode():Int;}, V> {
final map:HashMap<K, V>;
final keys:Iterator<K>;
public inline function new(map:HashMap<K, V>) {
this.map = map;
this.keys = map.keys();
}
/**
See `Iterator.hasNext`
**/
public inline function hasNext():Bool {
return keys.hasNext();
}
/**
See `Iterator.next`
**/
public inline function next():{key:K, value:V} {
var key = keys.next();
return {value: map.get(key), key: key};
}
}

View File

@ -0,0 +1,54 @@
/*
* 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 haxe.iterators;
import haxe.ds.IntMap;
/**
This Key/Value iterator can be used to iterate across maps.
**/
@:ifFeature("anon_read.keyValueIterator", "dynamic_read.keyValueIterator")
class MapKeyValueIterator<K, V> {
var map:haxe.Constraints.IMap<K, V>;
var keys:Iterator<K>;
public inline function new(map:haxe.Constraints.IMap<K, V>) {
this.map = map;
this.keys = map.keys();
}
/**
See `Iterator.hasNext`
**/
public inline function hasNext():Bool {
return keys.hasNext();
}
/**
See `Iterator.next`
**/
public inline function next():{key:K, value:V} {
var key = keys.next();
return {value: @:nullSafety(Off) (map.get(key) : V), key: key};
}
}

View File

@ -0,0 +1,19 @@
package haxe.iterators;
class RestIterator<T> {
final args:Rest<T>;
var current:Int = 0;
@:allow(haxe.Rest)
inline function new(args:Any) {
this.args = args;
}
public inline function hasNext():Bool {
return current < args.length;
}
public inline function next():T {
return args[current++];
}
}

Some files were not shown because too many files have changed in this diff Show More