Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
THRIFT-3022 Compact protocol for Haxe
Client: Haxe Patch: Jens Geyer This closes #388
- Loading branch information
Showing
9 changed files
with
1,162 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.apache.thrift.helper; | ||
|
||
import haxe.Int64; | ||
import haxe.io.Bytes; | ||
import haxe.io.BytesBuffer; | ||
|
||
class BitConverter { | ||
|
||
public static function DoubleToInt64Bits( db : Float) : Int64 { | ||
var buf = new BytesBuffer(); | ||
buf.addDouble( db); | ||
return bytesToLong( buf.getBytes()); | ||
} | ||
|
||
|
||
public static function Int64BitsToDouble( i64 : Int64) : Float { | ||
var buf = new BytesBuffer(); | ||
buf.add( fixedLongToBytes( i64)); | ||
return buf.getBytes().getDouble(0); | ||
} | ||
|
||
|
||
|
||
/** | ||
* Convert a long into little-endian bytes in buf starting at off and going | ||
* until off+7. | ||
*/ | ||
public static function fixedLongToBytes( n : Int64) : Bytes { | ||
var buf = Bytes.alloc(8); | ||
buf.set( 0, Int64.getLow( Int64.and( n, Int64.make(0, 0xff)))); | ||
buf.set( 1, Int64.getLow( Int64.and( Int64.shr( n, 8), Int64.make(0, 0xff)))); | ||
buf.set( 2, Int64.getLow( Int64.and( Int64.shr( n, 16), Int64.make(0, 0xff)))); | ||
buf.set( 3, Int64.getLow( Int64.and( Int64.shr( n, 24), Int64.make(0, 0xff)))); | ||
buf.set( 4, Int64.getLow( Int64.and( Int64.shr( n, 32), Int64.make(0, 0xff)))); | ||
buf.set( 5, Int64.getLow( Int64.and( Int64.shr( n, 40), Int64.make(0, 0xff)))); | ||
buf.set( 6, Int64.getLow( Int64.and( Int64.shr( n, 48), Int64.make(0, 0xff)))); | ||
buf.set( 7, Int64.getLow( Int64.and( Int64.shr( n, 56), Int64.make(0, 0xff)))); | ||
return buf; | ||
} | ||
|
||
/** | ||
* Note that it's important that the mask bytes are long literals, | ||
* otherwise they'll default to ints, and when you shift an int left 56 bits, | ||
* you just get a messed up int. | ||
*/ | ||
public static function bytesToLong( bytes : Bytes) : Int64 { | ||
var result : Int64 = Int64.make(0, 0); | ||
result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(7))); | ||
result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(6))); | ||
result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(5))); | ||
result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(4))); | ||
result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(3))); | ||
result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(2))); | ||
result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(1))); | ||
result = Int64.or( Int64.shl( result, 8), Int64.make( 0, bytes.get(0))); | ||
return result; | ||
} | ||
|
||
|
||
#if debug | ||
private static function TestBTL( test : Int64) : Void { | ||
var buf : Bytes = fixedLongToBytes( test); | ||
var erg = bytesToLong(buf); | ||
if ( Int64.compare( erg, test) != 0) | ||
throw 'BitConverter.bytesToLongTest($test) failed: $erg'; | ||
} | ||
#end | ||
|
||
|
||
#if debug | ||
private static function TestPair( a : Float, b : Int64) : Void { | ||
var bx = DoubleToInt64Bits(a); | ||
if ( Int64.compare( bx, b) != 0) | ||
throw 'BitConverter.TestPair: DoubleToInt64Bits($a): expected $b, got $bx'; | ||
var ax = Int64BitsToDouble(b); | ||
if( ax != a) | ||
throw 'BitConverter.TestPair: Int64BitsToDouble($b: expected $a, got $ax'; | ||
} | ||
#end | ||
|
||
|
||
#if debug | ||
public static function UnitTest() : Void { | ||
|
||
// bytesToLong() | ||
var i : Int; | ||
TestBTL( Int64.make(0,0)); | ||
for ( i in 0 ... 62) { | ||
TestBTL( Int64.shl( Int64.make(0,1), i)); | ||
TestBTL( Int64.sub( Int64.make(0,0), Int64.shl( Int64.make(0,1), i))); | ||
} | ||
TestBTL( Int64.make(0x7FFFFFFF,0xFFFFFFFF)); | ||
TestBTL( Int64.make(cast(0x80000000,Int),0x00000000)); | ||
|
||
// DoubleToInt64Bits; | ||
TestPair( 1.0000000000000000E+000, Int64.make(cast(0x3FF00000,Int),cast(0x00000000,Int))); | ||
TestPair( 1.5000000000000000E+001, Int64.make(cast(0x402E0000,Int),cast(0x00000000,Int))); | ||
TestPair( 2.5500000000000000E+002, Int64.make(cast(0x406FE000,Int),cast(0x00000000,Int))); | ||
TestPair( 4.2949672950000000E+009, Int64.make(cast(0x41EFFFFF,Int),cast(0xFFE00000,Int))); | ||
TestPair( 3.9062500000000000E-003, Int64.make(cast(0x3F700000,Int),cast(0x00000000,Int))); | ||
TestPair( 2.3283064365386963E-010, Int64.make(cast(0x3DF00000,Int),cast(0x00000000,Int))); | ||
TestPair( 1.2345678901230000E-300, Int64.make(cast(0x01AA74FE,Int),cast(0x1C1E7E45,Int))); | ||
TestPair( 1.2345678901234500E-150, Int64.make(cast(0x20D02A36,Int),cast(0x586DB4BB,Int))); | ||
TestPair( 1.2345678901234565E+000, Int64.make(cast(0x3FF3C0CA,Int),cast(0x428C59FA,Int))); | ||
TestPair( 1.2345678901234567E+000, Int64.make(cast(0x3FF3C0CA,Int),cast(0x428C59FB,Int))); | ||
TestPair( 1.2345678901234569E+000, Int64.make(cast(0x3FF3C0CA,Int),cast(0x428C59FC,Int))); | ||
TestPair( 1.2345678901234569E+150, Int64.make(cast(0x5F182344,Int),cast(0xCD3CDF9F,Int))); | ||
TestPair( 1.2345678901234569E+300, Int64.make(cast(0x7E3D7EE8,Int),cast(0xBCBBD352,Int))); | ||
TestPair( -1.7976931348623157E+308, Int64.make(cast(0xFFEFFFFF,Int),cast(0xFFFFFFFF,Int))); | ||
TestPair( 1.7976931348623157E+308, Int64.make(cast(0x7FEFFFFF,Int),cast(0xFFFFFFFF,Int))); | ||
TestPair( 4.9406564584124654E-324, Int64.make(cast(0x00000000,Int),cast(0x00000001,Int))); | ||
TestPair( 0.0000000000000000E+000, Int64.make(cast(0x00000000,Int),cast(0x00000000,Int))); | ||
TestPair( 4.94065645841247E-324, Int64.make(cast(0x00000000,Int),cast(0x00000001,Int))); | ||
TestPair( 3.2378592100206092E-319, Int64.make(cast(0x00000000,Int),cast(0x0000FFFF,Int))); | ||
TestPair( 1.3906711615669959E-309, Int64.make(cast(0x0000FFFF,Int),cast(0xFFFFFFFF,Int))); | ||
TestPair( Math.NEGATIVE_INFINITY, Int64.make(cast(0xFFF00000,Int),cast(0x00000000,Int))); | ||
TestPair( Math.POSITIVE_INFINITY, Int64.make(cast(0x7FF00000,Int),cast(0x00000000,Int))); | ||
|
||
// NaN is special | ||
var i64nan = DoubleToInt64Bits( Math.NaN); | ||
var i64cmp = Int64.make(cast(0xFFF80000, Int), cast(0x00000000, Int)); | ||
if ( ! Math.isNaN( Int64BitsToDouble( i64cmp))) | ||
throw 'BitConverter NaN-Test #1: expected NaN'; | ||
|
||
// For doubles, a quiet NaN is a bit pattern | ||
// between 7FF8000000000000 and 7FFFFFFFFFFFFFFF | ||
// or FFF8000000000000 and FFFFFFFFFFFFFFFF | ||
var min1 = Int64.make( cast(0x7FF80000, Int), cast(0x00000000, Int)); | ||
var max1 = Int64.make( cast(0x7FFFFFFF, Int), cast(0xFFFFFFFF, Int)); | ||
var min2 = Int64.make( cast(0xFFF80000, Int), cast(0x00000000, Int)); | ||
var max2 = Int64.make( cast(0xFFFFFFFF, Int), cast(0xFFFFFFFF, Int)); | ||
var ok1 = (Int64.compare( min1, i64nan) <= 0) && (Int64.compare( i64nan, max1) <= 0); | ||
var ok2 = (Int64.compare( min2, i64nan) <= 0) && (Int64.compare( i64nan, max2) <= 0); | ||
if( ! (ok1 || ok2)) | ||
throw 'BitConverter NaN-Test #2: failed'; | ||
} | ||
#end | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
package org.apache.thrift.helper; | ||
|
||
import haxe.Int64; | ||
|
||
class ZigZag { | ||
|
||
/** | ||
* Convert n into a zigzag int. This allows negative numbers to be | ||
* represented compactly as a varint. | ||
*/ | ||
public static function FromInt( n : Int) : UInt { | ||
return cast(n << 1,UInt) ^ cast(n >> 31,UInt); | ||
} | ||
|
||
|
||
/** | ||
* Convert from zigzag int to int. | ||
*/ | ||
public static function ToInt( n : UInt) : Int { | ||
return (0x7FFFFFFF & cast(n >> 1,Int)) ^ (-cast(n & 1,Int)); | ||
} | ||
|
||
|
||
/** | ||
* Convert l into a zigzag long. This allows negative numbers to be | ||
* represented compactly as a varint. | ||
*/ | ||
public static function FromLong( n : Int64) : Int64 { | ||
return Int64.xor( Int64.shl(n, 1), Int64.shr(n, 63)); | ||
} | ||
|
||
|
||
/** | ||
* Convert from zigzag long to long. | ||
*/ | ||
public static function ToLong( n : Int64) : Int64 { | ||
return Int64.xor( | ||
Int64.and( | ||
Int64.shr(n, 1), | ||
Int64.make(0x7FFFFFFF, 0xFFFFFFFF)), | ||
Int64.sub( | ||
Int64.make(0, 0), | ||
Int64.and(n, Int64.make(0,1)))); | ||
} | ||
|
||
|
||
#if debug | ||
private static function Test32( test : Int) : Void { | ||
var a : UInt = ZigZag.FromInt( test); | ||
var b : Int = ZigZag.ToInt(a); | ||
if( test != b) | ||
throw 'ZigZag.Test32($test) failed: a = $a, b = $b'; | ||
} | ||
#end | ||
|
||
|
||
|
||
#if debug | ||
private static function Test64( test : haxe.Int64) : Void { | ||
var a : Int64 = ZigZag.FromLong( test); | ||
var b : Int64 = ZigZag.ToLong(a); | ||
if( Int64.compare( test, b) != 0) | ||
throw 'ZigZag.Test64($test) failed: a = $a, b = $b'; | ||
} | ||
#end | ||
|
||
|
||
#if debug | ||
public static function UnitTest() : Void { | ||
var u1 : UInt = 0xFFFFFFFE; | ||
var u2 : UInt = 0xFFFFFFFF; | ||
|
||
// protobuf testcases | ||
if( FromInt(0) != 0) throw 'pb #1 to ZigZag'; | ||
if( FromInt(-1) != 1) throw 'pb #2 to ZigZag'; | ||
if( FromInt(1) != 2) throw 'pb #3 to ZigZag'; | ||
if( FromInt(-2) != 3) throw 'pb #4 to ZigZag'; | ||
if( FromInt(2147483647) != u1) throw 'pb #5 to ZigZag'; | ||
if( FromInt(-2147483648) != u2) throw 'pb #6 to ZigZag'; | ||
|
||
// protobuf testcases | ||
if( ToInt(0) != 0) throw 'pb #1 from ZigZag'; | ||
if( ToInt(1) != -1) throw 'pb #2 from ZigZag'; | ||
if( ToInt(2) != 1) throw 'pb #3 from ZigZag'; | ||
if( ToInt(3) != -2) throw 'pb #4 from ZigZag'; | ||
if( ToInt(u1) != 2147483647) throw 'pb #5 from ZigZag, got ${ToInt(u1)}'; | ||
if( ToInt(u2) != -2147483648) throw 'pb #6 from ZigZag, got ${ToInt(u2)}'; | ||
|
||
// back and forth 32 | ||
Test32( 0); | ||
for( i in 0 ... 30) { | ||
Test32( 1 << i); | ||
Test32( -(1 << i)); | ||
} | ||
Test32( 0x7FFFFFFF); | ||
Test32( cast(0x80000000,Int)); | ||
|
||
// back and forth 64 | ||
Test64( Int64.make(0,0)); | ||
for( i in 0 ... 62) { | ||
Test64( Int64.shl( Int64.make(0,1), i)); | ||
Test64( Int64.sub( Int64.make(0,0), Int64.shl( Int64.make(0,1), i))); | ||
} | ||
Test64( Int64.make(0x7FFFFFFF,0xFFFFFFFF)); | ||
Test64( Int64.make(cast(0x80000000,Int),0x00000000)); | ||
} | ||
#end | ||
} | ||
|
Oops, something went wrong.