Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
flatbuffers
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
flatbuffers
Commits
757854a6
Commit
757854a6
authored
Jan 07, 2015
by
Jon Simantov
Committed by
Android (Google) Code Review
Jan 07, 2015
Browse files
Options
Browse Files
Download
Plain Diff
Merge "C#: Allow ByteBuffer to use faster unsafe mode" into ub-games-master
parents
aa46f0e4
4390254e
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
241 additions
and
2 deletions
+241
-2
ByteBuffer.cs
net/FlatBuffers/ByteBuffer.cs
+213
-2
ByteBufferTests.cs
tests/FlatBuffers.Test/ByteBufferTests.cs
+28
-0
No files found.
net/FlatBuffers/ByteBuffer.cs
100644 → 100755
View file @
757854a6
...
...
@@ -14,13 +14,18 @@
* limitations under the License.
*/
//#define UNSAFE_BYTEBUFFER // uncomment this line to use faster ByteBuffer
using
System
;
using
System.Linq
;
namespace
FlatBuffers
{
/// <summary>
/// Class to mimick Java's ByteBuffer which is used heavily in Flatbuffers
/// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers.
/// If your execution environment allows unsafe code, you should enable
/// unsafe code in your project and #define UNSAFE_BYTEBUFFER to use a
/// MUCH faster version of ByteBuffer.
/// </summary>
public
class
ByteBuffer
{
...
...
@@ -39,11 +44,38 @@ namespace FlatBuffers
public
int
position
()
{
return
_pos
;
}
// Helper functions for the unsafe version.
static
public
ushort
ReverseBytes
(
ushort
input
)
{
return
(
ushort
)(((
input
&
0x00FFU
)
<<
8
)
|
((
input
&
0xFF00U
)
>>
8
));
}
static
public
uint
ReverseBytes
(
uint
input
)
{
return
((
input
&
0x000000FFU
)
<<
24
)
|
((
input
&
0x0000FF00U
)
<<
8
)
|
((
input
&
0x00FF0000U
)
>>
8
)
|
((
input
&
0xFF000000U
)
>>
24
);
}
static
public
ulong
ReverseBytes
(
ulong
input
)
{
return
(((
input
&
0x00000000000000FFU
L
)
<<
56
)
|
((
input
&
0x000000000000FF00U
L
)
<<
40
)
|
((
input
&
0x0000000000FF0000U
L
)
<<
24
)
|
((
input
&
0x00000000FF000000U
L
)
<<
8
)
|
((
input
&
0x000000FF00000000U
L
)
>>
8
)
|
((
input
&
0x0000FF0000000000U
L
)
>>
24
)
|
((
input
&
0x00FF000000000000U
L
)
>>
40
)
|
((
input
&
0xFF00000000000000U
L
)
>>
56
));
}
#if !UNSAFE_BYTEBUFFER
// Helper functions for the safe (but slower) version.
protected
void
WriteLittleEndian
(
int
offset
,
byte
[]
data
)
{
if
(!
BitConverter
.
IsLittleEndian
)
{
data
=
data
.
Reverse
().
ToArray
(
);
Array
.
Reverse
(
data
,
0
,
data
.
Length
);
}
Buffer
.
BlockCopy
(
data
,
0
,
_buffer
,
offset
,
data
.
Length
);
_pos
=
offset
;
...
...
@@ -58,6 +90,7 @@ namespace FlatBuffers
?
tmp
:
tmp
.
Reverse
().
ToArray
();
}
#endif // !UNSAFE_BYTEBUFFER
private
void
AssertOffsetAndLength
(
int
offset
,
int
length
)
{
...
...
@@ -81,6 +114,96 @@ namespace FlatBuffers
_pos
=
offset
;
}
#if UNSAFE_BYTEBUFFER
// Unsafe but more efficient versions of Put*.
public
void
PutShort
(
int
offset
,
short
value
)
{
PutUshort
(
offset
,
(
ushort
)
value
);
}
public
unsafe
void
PutUshort
(
int
offset
,
ushort
value
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
ushort
));
fixed
(
byte
*
ptr
=
_buffer
)
{
*(
ushort
*)(
ptr
+
offset
)
=
BitConverter
.
IsLittleEndian
?
value
:
ReverseBytes
(
value
);
}
_pos
=
offset
;
}
public
void
PutInt
(
int
offset
,
int
value
)
{
PutUint
(
offset
,
(
uint
)
value
);
}
public
unsafe
void
PutUint
(
int
offset
,
uint
value
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
uint
));
fixed
(
byte
*
ptr
=
_buffer
)
{
*(
uint
*)(
ptr
+
offset
)
=
BitConverter
.
IsLittleEndian
?
value
:
ReverseBytes
(
value
);
}
_pos
=
offset
;
}
public
unsafe
void
PutLong
(
int
offset
,
long
value
)
{
PutUlong
(
offset
,
(
ulong
)
value
);
}
public
unsafe
void
PutUlong
(
int
offset
,
ulong
value
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
ulong
));
fixed
(
byte
*
ptr
=
_buffer
)
{
*(
ulong
*)(
ptr
+
offset
)
=
BitConverter
.
IsLittleEndian
?
value
:
ReverseBytes
(
value
);
}
_pos
=
offset
;
}
public
unsafe
void
PutFloat
(
int
offset
,
float
value
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
float
));
fixed
(
byte
*
ptr
=
_buffer
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
*(
float
*)(
ptr
+
offset
)
=
value
;
}
else
{
*(
uint
*)(
ptr
+
offset
)
=
ReverseBytes
(*(
uint
*)(&
value
));
}
}
_pos
=
offset
;
}
public
unsafe
void
PutDouble
(
int
offset
,
double
value
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
double
));
fixed
(
byte
*
ptr
=
_buffer
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
*(
double
*)(
ptr
+
offset
)
=
value
;
}
else
{
*(
ulong
*)(
ptr
+
offset
)
=
ReverseBytes
(*(
ulong
*)(
ptr
+
offset
));
}
}
_pos
=
offset
;
}
#else // !UNSAFE_BYTEBUFFER
// Slower versions of Put* for when unsafe code is not allowed.
public
void
PutShort
(
int
offset
,
short
value
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
short
));
...
...
@@ -129,6 +252,8 @@ namespace FlatBuffers
WriteLittleEndian
(
offset
,
BitConverter
.
GetBytes
(
value
));
}
#endif // UNSAFE_BYTEBUFFER
public
sbyte
GetSbyte
(
int
index
)
{
AssertOffsetAndLength
(
index
,
sizeof
(
sbyte
));
...
...
@@ -141,6 +266,91 @@ namespace FlatBuffers
return
_buffer
[
index
];
}
#if UNSAFE_BYTEBUFFER
// Unsafe but more efficient versions of Get*.
public
short
GetShort
(
int
offset
)
{
return
(
short
)
GetUshort
(
offset
);
}
public
unsafe
ushort
GetUshort
(
int
offset
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
ushort
));
fixed
(
byte
*
ptr
=
_buffer
)
{
return
BitConverter
.
IsLittleEndian
?
*(
ushort
*)(
ptr
+
offset
)
:
ReverseBytes
(*(
ushort
*)(
ptr
+
offset
));
}
}
public
int
GetInt
(
int
offset
)
{
return
(
int
)
GetUint
(
offset
);
}
public
unsafe
uint
GetUint
(
int
offset
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
uint
));
fixed
(
byte
*
ptr
=
_buffer
)
{
return
BitConverter
.
IsLittleEndian
?
*(
uint
*)(
ptr
+
offset
)
:
ReverseBytes
(*(
uint
*)(
ptr
+
offset
));
}
}
public
long
GetLong
(
int
offset
)
{
return
(
long
)
GetUlong
(
offset
);
}
public
unsafe
ulong
GetUlong
(
int
offset
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
ulong
));
fixed
(
byte
*
ptr
=
_buffer
)
{
return
BitConverter
.
IsLittleEndian
?
*(
ulong
*)(
ptr
+
offset
)
:
ReverseBytes
(*(
ulong
*)(
ptr
+
offset
));
}
}
public
unsafe
float
GetFloat
(
int
offset
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
float
));
fixed
(
byte
*
ptr
=
_buffer
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
return
*(
float
*)(
ptr
+
offset
);
}
else
{
uint
uvalue
=
ReverseBytes
(*(
uint
*)(
ptr
+
offset
));
return
*(
float
*)(&
uvalue
);
}
}
}
public
unsafe
double
GetDouble
(
int
offset
)
{
AssertOffsetAndLength
(
offset
,
sizeof
(
double
));
fixed
(
byte
*
ptr
=
_buffer
)
{
if
(
BitConverter
.
IsLittleEndian
)
{
return
*(
double
*)(
ptr
+
offset
);
}
else
{
ulong
uvalue
=
ReverseBytes
(*(
ulong
*)(
ptr
+
offset
));
return
*(
double
*)(&
uvalue
);
}
}
}
#else // !UNSAFE_BYTEBUFFER
// Slower versions of Get* for when unsafe code is not allowed.
public
short
GetShort
(
int
index
)
{
var
tmp
=
ReadLittleEndian
(
index
,
sizeof
(
short
));
...
...
@@ -196,5 +406,6 @@ namespace FlatBuffers
var
value
=
BitConverter
.
ToDouble
(
tmp
,
0
);
return
value
;
}
#endif // UNSAFE_BYTEBUFFER
}
}
tests/FlatBuffers.Test/ByteBufferTests.cs
View file @
757854a6
...
...
@@ -239,6 +239,34 @@ namespace FlatBuffers.Test
var
uut
=
new
ByteBuffer
(
buffer
);
Assert
.
Throws
<
ArgumentOutOfRangeException
>(()
=>
uut
.
GetLong
(
0
));
}
public
void
ByteBuffer_ReverseBytesUshort
()
{
ushort
original
=
(
ushort
)
0x1234U
;
ushort
reverse
=
ByteBuffer
.
ReverseBytes
(
original
);
Assert
.
AreEqual
(
0x3412U
,
reverse
);
ushort
rereverse
=
ByteBuffer
.
ReverseBytes
(
reverse
);
Assert
.
AreEqual
(
original
,
rereverse
);
}
public
void
ByteBuffer_ReverseBytesUint
()
{
uint
original
=
0x12345678
;
uint
reverse
=
ByteBuffer
.
ReverseBytes
(
original
);
Assert
.
AreEqual
(
0x78563412U
,
reverse
);
uint
rereverse
=
ByteBuffer
.
ReverseBytes
(
reverse
);
Assert
.
AreEqual
(
original
,
rereverse
);
}
public
void
ByteBuffer_ReverseBytesUlong
()
{
ulong
original
=
0x1234567890ABCDEFU
L
;
ulong
reverse
=
ByteBuffer
.
ReverseBytes
(
original
);
Assert
.
AreEqual
(
0xEFCDAB9078563412U
L
,
reverse
);
ulong
rereverse
=
ByteBuffer
.
ReverseBytes
(
reverse
);
Assert
.
AreEqual
(
original
,
rereverse
);
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment