You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2015/09/21 16:27:33 UTC
[37/52] [partial] ignite git commit: IGNITE-1513: Moved .Net.
http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/PlatformTarget.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/PlatformTarget.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/PlatformTarget.cs
new file mode 100644
index 0000000..67f631a
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/PlatformTarget.cs
@@ -0,0 +1,715 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.CodeAnalysis;
+ using System.IO;
+ using Apache.Ignite.Core.Common;
+ using Apache.Ignite.Core.Impl.Common;
+ using Apache.Ignite.Core.Impl.Memory;
+ using Apache.Ignite.Core.Impl.Portable;
+ using Apache.Ignite.Core.Impl.Portable.IO;
+ using Apache.Ignite.Core.Impl.Portable.Metadata;
+ using Apache.Ignite.Core.Impl.Unmanaged;
+ using Apache.Ignite.Core.Portable;
+ using UU = Apache.Ignite.Core.Impl.Unmanaged.UnmanagedUtils;
+
+ /// <summary>
+ /// Base class for interop targets.
+ /// </summary>
+ [SuppressMessage("ReSharper", "LocalVariableHidesMember")]
+ internal abstract class PlatformTarget
+ {
+ /** */
+ protected const int True = 1;
+
+ /** */
+ private const int OpMeta = -1;
+
+ /** */
+ public const int OpNone = -2;
+
+ /** */
+ private static readonly Dictionary<Type, FutureType> IgniteFutureTypeMap
+ = new Dictionary<Type, FutureType>
+ {
+ {typeof(bool), FutureType.Bool},
+ {typeof(byte), FutureType.Byte},
+ {typeof(char), FutureType.Char},
+ {typeof(double), FutureType.Double},
+ {typeof(float), FutureType.Float},
+ {typeof(int), FutureType.Int},
+ {typeof(long), FutureType.Long},
+ {typeof(short), FutureType.Short}
+ };
+
+ /** Unmanaged target. */
+ private readonly IUnmanagedTarget _target;
+
+ /** Marshaller. */
+ private readonly PortableMarshaller _marsh;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="target">Target.</param>
+ /// <param name="marsh">Marshaller.</param>
+ protected PlatformTarget(IUnmanagedTarget target, PortableMarshaller marsh)
+ {
+ _target = target;
+ _marsh = marsh;
+ }
+
+ /// <summary>
+ /// Unmanaged target.
+ /// </summary>
+ internal IUnmanagedTarget Target
+ {
+ get { return _target; }
+ }
+
+ /// <summary>
+ /// Marshaller.
+ /// </summary>
+ internal PortableMarshaller Marshaller
+ {
+ get { return _marsh; }
+ }
+
+ #region Static Helpers
+
+ /// <summary>
+ /// Write collection.
+ /// </summary>
+ /// <param name="writer">Portable writer.</param>
+ /// <param name="vals">Values.</param>
+ /// <returns>The same writer for chaining.</returns>
+ protected static PortableWriterImpl WriteCollection<T>(PortableWriterImpl writer, ICollection<T> vals)
+ {
+ return WriteCollection<T, T>(writer, vals, null);
+ }
+
+ /// <summary>
+ /// Write nullable collection.
+ /// </summary>
+ /// <param name="writer">Portable writer.</param>
+ /// <param name="vals">Values.</param>
+ /// <returns>The same writer for chaining.</returns>
+ protected static PortableWriterImpl WriteNullableCollection<T>(PortableWriterImpl writer, ICollection<T> vals)
+ {
+ return WriteNullable(writer, vals, WriteCollection);
+ }
+
+ /// <summary>
+ /// Write collection.
+ /// </summary>
+ /// <param name="writer">Portable writer.</param>
+ /// <param name="vals">Values.</param>
+ /// <param name="selector">A transform function to apply to each element.</param>
+ /// <returns>The same writer for chaining.</returns>
+ protected static PortableWriterImpl WriteCollection<T1, T2>(PortableWriterImpl writer,
+ ICollection<T1> vals, Func<T1, T2> selector)
+ {
+ writer.WriteInt(vals.Count);
+
+ if (selector == null)
+ {
+ foreach (var val in vals)
+ writer.Write(val);
+ }
+ else
+ {
+ foreach (var val in vals)
+ writer.Write(selector(val));
+ }
+
+ return writer;
+ }
+
+ /// <summary>
+ /// Write enumerable.
+ /// </summary>
+ /// <param name="writer">Portable writer.</param>
+ /// <param name="vals">Values.</param>
+ /// <returns>The same writer for chaining.</returns>
+ protected static PortableWriterImpl WriteEnumerable<T>(PortableWriterImpl writer, IEnumerable<T> vals)
+ {
+ return WriteEnumerable<T, T>(writer, vals, null);
+ }
+
+ /// <summary>
+ /// Write enumerable.
+ /// </summary>
+ /// <param name="writer">Portable writer.</param>
+ /// <param name="vals">Values.</param>
+ /// <param name="selector">A transform function to apply to each element.</param>
+ /// <returns>The same writer for chaining.</returns>
+ protected static PortableWriterImpl WriteEnumerable<T1, T2>(PortableWriterImpl writer,
+ IEnumerable<T1> vals, Func<T1, T2> selector)
+ {
+ var col = vals as ICollection<T1>;
+
+ if (col != null)
+ return WriteCollection(writer, col, selector);
+
+ var stream = writer.Stream;
+
+ var pos = stream.Position;
+
+ stream.Seek(4, SeekOrigin.Current);
+
+ var size = 0;
+
+ if (selector == null)
+ {
+ foreach (var val in vals)
+ {
+ writer.Write(val);
+
+ size++;
+ }
+ }
+ else
+ {
+ foreach (var val in vals)
+ {
+ writer.Write(selector(val));
+
+ size++;
+ }
+ }
+
+ stream.WriteInt(pos, size);
+
+ return writer;
+ }
+
+ /// <summary>
+ /// Write dictionary.
+ /// </summary>
+ /// <param name="writer">Portable writer.</param>
+ /// <param name="vals">Values.</param>
+ /// <returns>The same writer.</returns>
+ protected static PortableWriterImpl WriteDictionary<T1, T2>(PortableWriterImpl writer,
+ IDictionary<T1, T2> vals)
+ {
+ writer.WriteInt(vals.Count);
+
+ foreach (KeyValuePair<T1, T2> pair in vals)
+ {
+ writer.Write(pair.Key);
+ writer.Write(pair.Value);
+ }
+
+ return writer;
+ }
+
+ /// <summary>
+ /// Write a nullable item.
+ /// </summary>
+ /// <param name="writer">Portable writer.</param>
+ /// <param name="item">Item.</param>
+ /// <param name="writeItem">Write action to perform on item when it is not null.</param>
+ /// <returns>The same writer for chaining.</returns>
+ protected static PortableWriterImpl WriteNullable<T>(PortableWriterImpl writer, T item,
+ Func<PortableWriterImpl, T, PortableWriterImpl> writeItem)
+ {
+ if (item == null)
+ {
+ writer.WriteBoolean(false);
+
+ return writer;
+ }
+
+ writer.WriteBoolean(true);
+
+ return writeItem(writer, item);
+ }
+
+ #endregion
+
+ #region OUT operations
+
+ /// <summary>
+ /// Perform out operation.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="action">Action to be performed on the stream.</param>
+ /// <returns></returns>
+ protected long DoOutOp(int type, Action<IPortableStream> action)
+ {
+ using (var stream = IgniteManager.Memory.Allocate().Stream())
+ {
+ action(stream);
+
+ return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+ }
+ }
+
+ /// <summary>
+ /// Perform out operation.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="action">Action to be performed on the stream.</param>
+ /// <returns></returns>
+ protected long DoOutOp(int type, Action<PortableWriterImpl> action)
+ {
+ using (var stream = IgniteManager.Memory.Allocate().Stream())
+ {
+ var writer = _marsh.StartMarshal(stream);
+
+ action(writer);
+
+ FinishMarshal(writer);
+
+ return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+ }
+ }
+
+ /// <summary>
+ /// Perform simple output operation accepting single argument.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="val1">Value.</param>
+ /// <returns>Result.</returns>
+ protected long DoOutOp<T1>(int type, T1 val1)
+ {
+ return DoOutOp(type, writer =>
+ {
+ writer.Write(val1);
+ });
+ }
+
+ /// <summary>
+ /// Perform simple output operation accepting two arguments.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="val1">Value 1.</param>
+ /// <param name="val2">Value 2.</param>
+ /// <returns>Result.</returns>
+ protected long DoOutOp<T1, T2>(int type, T1 val1, T2 val2)
+ {
+ return DoOutOp(type, writer =>
+ {
+ writer.Write(val1);
+ writer.Write(val2);
+ });
+ }
+
+ /// <summary>
+ /// Perform simple output operation accepting three arguments.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="val1">Value 1.</param>
+ /// <param name="val2">Value 2.</param>
+ /// <param name="val3">Value 3.</param>
+ /// <returns>Result.</returns>
+ protected long DoOutOp<T1, T2, T3>(int type, T1 val1, T2 val2, T3 val3)
+ {
+ return DoOutOp(type, writer =>
+ {
+ writer.Write(val1);
+ writer.Write(val2);
+ writer.Write(val3);
+ });
+ }
+
+ #endregion
+
+ #region IN operations
+
+ /// <summary>
+ /// Perform in operation.
+ /// </summary>
+ /// <param name="type">Type.</param>
+ /// <param name="action">Action.</param>
+ protected void DoInOp(int type, Action<IPortableStream> action)
+ {
+ using (var stream = IgniteManager.Memory.Allocate().Stream())
+ {
+ UU.TargetOutStream(_target, type, stream.MemoryPointer);
+
+ stream.SynchronizeInput();
+
+ action(stream);
+ }
+ }
+
+ /// <summary>
+ /// Perform in operation.
+ /// </summary>
+ /// <param name="type">Type.</param>
+ /// <param name="action">Action.</param>
+ /// <returns>Result.</returns>
+ protected T DoInOp<T>(int type, Func<IPortableStream, T> action)
+ {
+ using (var stream = IgniteManager.Memory.Allocate().Stream())
+ {
+ UU.TargetOutStream(_target, type, stream.MemoryPointer);
+
+ stream.SynchronizeInput();
+
+ return action(stream);
+ }
+ }
+
+ /// <summary>
+ /// Perform simple in operation returning immediate result.
+ /// </summary>
+ /// <param name="type">Type.</param>
+ /// <returns>Result.</returns>
+ protected T DoInOp<T>(int type)
+ {
+ using (var stream = IgniteManager.Memory.Allocate().Stream())
+ {
+ UU.TargetOutStream(_target, type, stream.MemoryPointer);
+
+ stream.SynchronizeInput();
+
+ return Unmarshal<T>(stream);
+ }
+ }
+
+ #endregion
+
+ #region OUT-IN operations
+
+ /// <summary>
+ /// Perform out-in operation.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="outAction">Out action.</param>
+ /// <param name="inAction">In action.</param>
+ protected void DoOutInOp(int type, Action<PortableWriterImpl> outAction, Action<IPortableStream> inAction)
+ {
+ using (PlatformMemoryStream outStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ using (PlatformMemoryStream inStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ PortableWriterImpl writer = _marsh.StartMarshal(outStream);
+
+ outAction(writer);
+
+ FinishMarshal(writer);
+
+ UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+
+ inStream.SynchronizeInput();
+
+ inAction(inStream);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Perform out-in operation.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="outAction">Out action.</param>
+ /// <param name="inAction">In action.</param>
+ /// <returns>Result.</returns>
+ protected TR DoOutInOp<TR>(int type, Action<PortableWriterImpl> outAction, Func<IPortableStream, TR> inAction)
+ {
+ using (PlatformMemoryStream outStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ using (PlatformMemoryStream inStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ PortableWriterImpl writer = _marsh.StartMarshal(outStream);
+
+ outAction(writer);
+
+ FinishMarshal(writer);
+
+ UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+
+ inStream.SynchronizeInput();
+
+ return inAction(inStream);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Perform out-in operation.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="outAction">Out action.</param>
+ /// <param name="inAction">In action.</param>
+ /// <param name="arg">Argument.</param>
+ /// <returns>Result.</returns>
+ protected unsafe TR DoOutInOp<TR>(int type, Action<PortableWriterImpl> outAction, Func<IPortableStream, TR> inAction, void* arg)
+ {
+ using (PlatformMemoryStream outStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ using (PlatformMemoryStream inStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ PortableWriterImpl writer = _marsh.StartMarshal(outStream);
+
+ outAction(writer);
+
+ FinishMarshal(writer);
+
+ UU.TargetInObjectStreamOutStream(_target, type, arg, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+
+ inStream.SynchronizeInput();
+
+ return inAction(inStream);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Perform out-in operation.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="outAction">Out action.</param>
+ /// <returns>Result.</returns>
+ protected TR DoOutInOp<TR>(int type, Action<PortableWriterImpl> outAction)
+ {
+ using (PlatformMemoryStream outStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ using (PlatformMemoryStream inStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ PortableWriterImpl writer = _marsh.StartMarshal(outStream);
+
+ outAction(writer);
+
+ FinishMarshal(writer);
+
+ UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+
+ inStream.SynchronizeInput();
+
+ return Unmarshal<TR>(inStream);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Perform simple out-in operation accepting single argument.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="val">Value.</param>
+ /// <returns>Result.</returns>
+ protected TR DoOutInOp<T1, TR>(int type, T1 val)
+ {
+ using (PlatformMemoryStream outStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ using (PlatformMemoryStream inStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ PortableWriterImpl writer = _marsh.StartMarshal(outStream);
+
+ writer.WriteObject(val);
+
+ FinishMarshal(writer);
+
+ UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+
+ inStream.SynchronizeInput();
+
+ return Unmarshal<TR>(inStream);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Perform simple out-in operation accepting two arguments.
+ /// </summary>
+ /// <param name="type">Operation type.</param>
+ /// <param name="val1">Value.</param>
+ /// <param name="val2">Value.</param>
+ /// <returns>Result.</returns>
+ protected TR DoOutInOp<T1, T2, TR>(int type, T1 val1, T2 val2)
+ {
+ using (PlatformMemoryStream outStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ using (PlatformMemoryStream inStream = IgniteManager.Memory.Allocate().Stream())
+ {
+ PortableWriterImpl writer = _marsh.StartMarshal(outStream);
+
+ writer.WriteObject(val1);
+ writer.WriteObject(val2);
+
+ FinishMarshal(writer);
+
+ UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+
+ inStream.SynchronizeInput();
+
+ return Unmarshal<TR>(inStream);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Miscelanneous
+
+ /// <summary>
+ /// Finish marshaling.
+ /// </summary>
+ /// <param name="writer">Portable writer.</param>
+ internal void FinishMarshal(PortableWriterImpl writer)
+ {
+ _marsh.FinishMarshal(writer);
+ }
+
+ /// <summary>
+ /// Put metadata to Grid.
+ /// </summary>
+ /// <param name="metas">Metadatas.</param>
+ internal void PutMetadata(IDictionary<int, IPortableMetadata> metas)
+ {
+ DoOutOp(OpMeta, stream =>
+ {
+ PortableWriterImpl metaWriter = _marsh.StartMarshal(stream);
+
+ metaWriter.WriteInt(metas.Count);
+
+ foreach (var meta in metas.Values)
+ {
+ PortableMetadataImpl meta0 = (PortableMetadataImpl)meta;
+
+ metaWriter.WriteInt(meta0.TypeId);
+ metaWriter.WriteString(meta0.TypeName);
+ metaWriter.WriteString(meta0.AffinityKeyFieldName);
+
+ IDictionary<string, int> fields = meta0.FieldsMap();
+
+ metaWriter.WriteInt(fields.Count);
+
+ foreach (var field in fields)
+ {
+ metaWriter.WriteString(field.Key);
+ metaWriter.WriteInt(field.Value);
+ }
+ }
+
+ _marsh.FinishMarshal(metaWriter);
+ });
+
+ _marsh.OnMetadataSent(metas);
+ }
+
+ /// <summary>
+ /// Unmarshal object using the given stream.
+ /// </summary>
+ /// <param name="stream">Stream.</param>
+ /// <returns>Unmarshalled object.</returns>
+ protected virtual T Unmarshal<T>(IPortableStream stream)
+ {
+ return _marsh.Unmarshal<T>(stream);
+ }
+
+ /// <summary>
+ /// Creates a future and starts listening.
+ /// </summary>
+ /// <typeparam name="T">Future result type</typeparam>
+ /// <param name="listenAction">The listen action.</param>
+ /// <param name="keepPortable">Keep portable flag, only applicable to object futures. False by default.</param>
+ /// <param name="convertFunc">The function to read future result from stream.</param>
+ /// <returns>Created future.</returns>
+ protected IFuture<T> GetFuture<T>(Action<long, int> listenAction, bool keepPortable = false,
+ Func<PortableReaderImpl, T> convertFunc = null)
+ {
+ var futType = FutureType.Object;
+
+ var type = typeof(T);
+
+ if (type.IsPrimitive)
+ IgniteFutureTypeMap.TryGetValue(type, out futType);
+
+ var fut = convertFunc == null && futType != FutureType.Object
+ ? new Future<T>()
+ : new Future<T>(new FutureConverter<T>(_marsh, keepPortable, convertFunc));
+
+ var futHnd = _marsh.Ignite.HandleRegistry.Allocate(fut);
+
+ listenAction(futHnd, (int)futType);
+
+ return fut;
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// PlatformTarget with IDisposable pattern.
+ /// </summary>
+ internal abstract class PlatformDisposableTarget : PlatformTarget, IDisposable
+ {
+ /** Disposed flag. */
+ private volatile bool _disposed;
+
+ /// <summary>
+ /// Constructor.
+ /// </summary>
+ /// <param name="target">Target.</param>
+ /// <param name="marsh">Marshaller.</param>
+ protected PlatformDisposableTarget(IUnmanagedTarget target, PortableMarshaller marsh) : base(target, marsh)
+ {
+ // No-op.
+ }
+
+ /** <inheritdoc /> */
+ public void Dispose()
+ {
+ lock (this)
+ {
+ if (_disposed)
+ return;
+
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+
+ _disposed = true;
+ }
+ }
+
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources.
+ /// </summary>
+ /// <param name="disposing">
+ /// <c>true</c> when called from Dispose; <c>false</c> when called from finalizer.
+ /// </param>
+ protected virtual void Dispose(bool disposing)
+ {
+ Target.Dispose();
+ }
+
+ /// <summary>
+ /// Throws <see cref="ObjectDisposedException"/> if this instance has been disposed.
+ /// </summary>
+ protected void ThrowIfDisposed()
+ {
+ if (_disposed)
+ throw new ObjectDisposedException(GetType().Name, "Object has been disposed.");
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance is disposed.
+ /// </summary>
+ protected bool IsDisposed
+ {
+ get { return _disposed; }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableSystemTypeSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableSystemTypeSerializer.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableSystemTypeSerializer.cs
new file mode 100644
index 0000000..3fee3ca
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableSystemTypeSerializer.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Portable
+{
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Serializer for system types that can create instances directly from a stream and does not support handles.
+ /// </summary>
+ internal interface IPortableSystemTypeSerializer : IPortableSerializer
+ {
+ /// <summary>
+ /// Reads the instance from a reader.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <returns>Deserialized instance.</returns>
+ object ReadInstance(PortableReaderImpl reader);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs
new file mode 100644
index 0000000..4a4f0dc
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Portable
+{
+ using System;
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Type descriptor.
+ /// </summary>
+ internal interface IPortableTypeDescriptor
+ {
+ /// <summary>
+ /// Type.
+ /// </summary>
+ Type Type
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Type ID.
+ /// </summary>
+ int TypeId
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Type name.
+ /// </summary>
+ string TypeName
+ {
+ get;
+ }
+
+ /// <summary>
+ /// User type flag.
+ /// </summary>
+ bool UserType
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Metadata enabled flag.
+ /// </summary>
+ bool MetadataEnabled
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Whether to cache deserialized value in IPortableObject
+ /// </summary>
+ bool KeepDeserialized
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Name converter.
+ /// </summary>
+ IPortableNameMapper NameConverter
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Mapper.
+ /// </summary>
+ IPortableIdMapper Mapper
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Serializer.
+ /// </summary>
+ IPortableSerializer Serializer
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Affinity key field name.
+ /// </summary>
+ string AffinityKeyFieldName
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Typed handler.
+ /// </summary>
+ object TypedHandler
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Untyped handler.
+ /// </summary>
+ PortableSystemWriteDelegate UntypedHandler
+ {
+ get;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableWriteAware.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableWriteAware.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableWriteAware.cs
new file mode 100644
index 0000000..d3c1521
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableWriteAware.cs
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Portable
+{
+ using Apache.Ignite.Core.Portable;
+
+ /// <summary>
+ /// Represents an object that can write itself to a portable writer.
+ /// </summary>
+ internal interface IPortableWriteAware
+ {
+ /// <summary>
+ /// Writes this object to the given writer.
+ /// </summary>
+ /// <param name="writer">Writer.</param>
+ /// <exception cref="System.IO.IOException">If write failed.</exception>
+ void WritePortable(IPortableWriter writer);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/Io/IPortableStream.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/Io/IPortableStream.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/Io/IPortableStream.cs
new file mode 100644
index 0000000..8111117
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/Io/IPortableStream.cs
@@ -0,0 +1,320 @@
+/*
+ * 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.
+ */
+
+
+namespace Apache.Ignite.Core.Impl.Portable.IO
+{
+ using System;
+ using System.IO;
+ using System.Text;
+
+ /// <summary>
+ /// Stream capable of working with portable objects.
+ /// </summary>
+ [CLSCompliant(false)]
+ public unsafe interface IPortableStream : IDisposable
+ {
+ /// <summary>
+ /// Write bool.
+ /// </summary>
+ /// <param name="val">Bool value.</param>
+ void WriteBool(bool val);
+
+ /// <summary>
+ /// Read bool.
+ /// </summary>
+ /// <returns>Bool value.</returns>
+ bool ReadBool();
+
+ /// <summary>
+ /// Write bool array.
+ /// </summary>
+ /// <param name="val">Bool array.</param>
+ void WriteBoolArray(bool[] val);
+
+ /// <summary>
+ /// Read bool array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Bool array.</returns>
+ bool[] ReadBoolArray(int cnt);
+
+ /// <summary>
+ /// Write byte.
+ /// </summary>
+ /// <param name="val">Byte value.</param>
+ void WriteByte(byte val);
+
+ /// <summary>
+ /// Read byte.
+ /// </summary>
+ /// <returns>Byte value.</returns>
+ byte ReadByte();
+
+ /// <summary>
+ /// Write byte array.
+ /// </summary>
+ /// <param name="val">Byte array.</param>
+ void WriteByteArray(byte[] val);
+
+ /// <summary>
+ /// Read byte array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Byte array.</returns>
+ byte[] ReadByteArray(int cnt);
+
+ /// <summary>
+ /// Write short.
+ /// </summary>
+ /// <param name="val">Short value.</param>
+ void WriteShort(short val);
+
+ /// <summary>
+ /// Read short.
+ /// </summary>
+ /// <returns>Short value.</returns>
+ short ReadShort();
+
+ /// <summary>
+ /// Write short array.
+ /// </summary>
+ /// <param name="val">Short array.</param>
+ void WriteShortArray(short[] val);
+
+ /// <summary>
+ /// Read short array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Short array.</returns>
+ short[] ReadShortArray(int cnt);
+
+ /// <summary>
+ /// Write char.
+ /// </summary>
+ /// <param name="val">Char value.</param>
+ void WriteChar(char val);
+
+ /// <summary>
+ /// Read char.
+ /// </summary>
+ /// <returns>Char value.</returns>
+ char ReadChar();
+
+ /// <summary>
+ /// Write char array.
+ /// </summary>
+ /// <param name="val">Char array.</param>
+ void WriteCharArray(char[] val);
+
+ /// <summary>
+ /// Read char array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Char array.</returns>
+ char[] ReadCharArray(int cnt);
+
+ /// <summary>
+ /// Write int.
+ /// </summary>
+ /// <param name="val">Int value.</param>
+ void WriteInt(int val);
+
+ /// <summary>
+ /// Write int to specific position.
+ /// </summary>
+ /// <param name="writePos">Position.</param>
+ /// <param name="val">Value.</param>
+ void WriteInt(int writePos, int val);
+
+ /// <summary>
+ /// Read int.
+ /// </summary>
+ /// <returns>Int value.</returns>
+ int ReadInt();
+
+ /// <summary>
+ /// Write int array.
+ /// </summary>
+ /// <param name="val">Int array.</param>
+ void WriteIntArray(int[] val);
+
+ /// <summary>
+ /// Read int array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Int array.</returns>
+ int[] ReadIntArray(int cnt);
+
+ /// <summary>
+ /// Write long.
+ /// </summary>
+ /// <param name="val">Long value.</param>
+ void WriteLong(long val);
+
+ /// <summary>
+ /// Read long.
+ /// </summary>
+ /// <returns>Long value.</returns>
+ long ReadLong();
+
+ /// <summary>
+ /// Write long array.
+ /// </summary>
+ /// <param name="val">Long array.</param>
+ void WriteLongArray(long[] val);
+
+ /// <summary>
+ /// Read long array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Long array.</returns>
+ long[] ReadLongArray(int cnt);
+
+ /// <summary>
+ /// Write float.
+ /// </summary>
+ /// <param name="val">Float value.</param>
+ void WriteFloat(float val);
+
+ /// <summary>
+ /// Read float.
+ /// </summary>
+ /// <returns>Float value.</returns>
+ float ReadFloat();
+
+ /// <summary>
+ /// Write float array.
+ /// </summary>
+ /// <param name="val">Float array.</param>
+ void WriteFloatArray(float[] val);
+
+ /// <summary>
+ /// Read float array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Float array.</returns>
+ float[] ReadFloatArray(int cnt);
+
+ /// <summary>
+ /// Write double.
+ /// </summary>
+ /// <param name="val">Double value.</param>
+ void WriteDouble(double val);
+
+ /// <summary>
+ /// Read double.
+ /// </summary>
+ /// <returns>Double value.</returns>
+ double ReadDouble();
+
+ /// <summary>
+ /// Write double array.
+ /// </summary>
+ /// <param name="val">Double array.</param>
+ void WriteDoubleArray(double[] val);
+
+ /// <summary>
+ /// Read double array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Double array.</returns>
+ double[] ReadDoubleArray(int cnt);
+
+ /// <summary>
+ /// Write string.
+ /// </summary>
+ /// <param name="chars">Characters.</param>
+ /// <param name="charCnt">Char count.</param>
+ /// <param name="byteCnt">Byte count.</param>
+ /// <param name="encoding">Encoding.</param>
+ /// <returns>Amounts of bytes written.</returns>
+ int WriteString(char* chars, int charCnt, int byteCnt, Encoding encoding);
+
+ /// <summary>
+ /// Write arbitrary data.
+ /// </summary>
+ /// <param name="src">Source array.</param>
+ /// <param name="off">Offset</param>
+ /// <param name="cnt">Count.</param>
+ void Write(byte[] src, int off, int cnt);
+
+ /// <summary>
+ /// Read arbitrary data.
+ /// </summary>
+ /// <param name="dest">Destination array.</param>
+ /// <param name="off">Offset.</param>
+ /// <param name="cnt">Count.</param>
+ /// <returns>Amount of bytes read.</returns>
+ void Read(byte[] dest, int off, int cnt);
+
+ /// <summary>
+ /// Write arbitrary data.
+ /// </summary>
+ /// <param name="src">Source.</param>
+ /// <param name="cnt">Count.</param>
+ void Write(byte* src, int cnt);
+
+ /// <summary>
+ /// Read arbitrary data.
+ /// </summary>
+ /// <param name="dest">Destination.</param>
+ /// <param name="cnt">Count.</param>
+ void Read(byte* dest, int cnt);
+
+ /// <summary>
+ /// Position.
+ /// </summary>
+ int Position
+ {
+ get;
+ }
+
+ /// <summary>
+ /// Gets remaining bytes in the stream.
+ /// </summary>
+ /// <returns>Remaining bytes.</returns>
+ int Remaining();
+
+ /// <summary>
+ /// Gets underlying array, avoiding copying if possible.
+ /// </summary>
+ /// <returns>Underlying array.</returns>
+ byte[] Array();
+
+ /// <summary>
+ /// Gets underlying data in a new array.
+ /// </summary>
+ /// <returns>New array with data.</returns>
+ byte[] ArrayCopy();
+
+ /// <summary>
+ /// Check whether array passed as argument is the same as the stream hosts.
+ /// </summary>
+ /// <param name="arr">Array.</param>
+ /// <returns><c>True</c> if they are same.</returns>
+ bool IsSameArray(byte[] arr);
+
+ /// <summary>
+ /// Seek to the given positoin.
+ /// </summary>
+ /// <param name="offset">Offset.</param>
+ /// <param name="origin">Seek origin.</param>
+ /// <returns>Position.</returns>
+ int Seek(int offset, SeekOrigin origin);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/f2eb16cd/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/Io/PortableAbstractStream.cs
----------------------------------------------------------------------
diff --git a/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/Io/PortableAbstractStream.cs b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/Io/PortableAbstractStream.cs
new file mode 100644
index 0000000..648d754
--- /dev/null
+++ b/modules/platform/dotnet/Apache.Ignite.Core/Impl/Portable/Io/PortableAbstractStream.cs
@@ -0,0 +1,1298 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Portable.IO
+{
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.IO;
+ using System.Reflection;
+ using System.Text;
+
+ /// <summary>
+ /// Base class for managed and unmanaged data streams.
+ /// </summary>
+ internal unsafe abstract class PortableAbstractStream : IPortableStream
+ {
+ /// <summary>
+ /// Array copy delegate.
+ /// </summary>
+ delegate void MemCopy(byte* a1, byte* a2, int len);
+
+ /** memcpy function handle. */
+ private static readonly MemCopy Memcpy;
+
+ /** Whether src and dest arguments are inverted. */
+ private static readonly bool MemcpyInverted;
+
+ /** Byte: zero. */
+ protected const byte ByteZero = 0;
+
+ /** Byte: one. */
+ protected const byte ByteOne = 1;
+
+ /** LITTLE_ENDIAN flag. */
+ protected static readonly bool LittleEndian = BitConverter.IsLittleEndian;
+
+ /** Position. */
+ protected int Pos;
+
+ /** Disposed flag. */
+ private bool _disposed;
+
+ /// <summary>
+ /// Static initializer.
+ /// </summary>
+ [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
+ static PortableAbstractStream()
+ {
+ Type type = typeof(Buffer);
+
+ const BindingFlags flags = BindingFlags.Static | BindingFlags.NonPublic;
+ Type[] paramTypes = { typeof(byte*), typeof(byte*), typeof(int) };
+
+ // Assume .Net 4.5.
+ MethodInfo mthd = type.GetMethod("Memcpy", flags, null, paramTypes, null);
+
+ MemcpyInverted = true;
+
+ if (mthd == null)
+ {
+ // Assume .Net 4.0.
+ mthd = type.GetMethod("memcpyimpl", flags, null, paramTypes, null);
+
+ MemcpyInverted = false;
+
+ if (mthd == null)
+ throw new InvalidOperationException("Unable to get memory copy function delegate.");
+ }
+
+ Memcpy = (MemCopy)Delegate.CreateDelegate(typeof(MemCopy), mthd);
+ }
+
+ /// <summary>
+ /// Write byte.
+ /// </summary>
+ /// <param name="val">Byte value.</param>
+ public abstract void WriteByte(byte val);
+
+ /// <summary>
+ /// Read byte.
+ /// </summary>
+ /// <returns>
+ /// Byte value.
+ /// </returns>
+ public abstract byte ReadByte();
+
+ /// <summary>
+ /// Write byte array.
+ /// </summary>
+ /// <param name="val">Byte array.</param>
+ public abstract void WriteByteArray(byte[] val);
+
+ /// <summary>
+ /// Internal routine to write byte array.
+ /// </summary>
+ /// <param name="val">Byte array.</param>
+ /// <param name="data">Data pointer.</param>
+ protected void WriteByteArray0(byte[] val, byte* data)
+ {
+ fixed (byte* val0 = val)
+ {
+ CopyMemory(val0, data, val.Length);
+ }
+ }
+
+ /// <summary>
+ /// Read byte array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Byte array.
+ /// </returns>
+ public abstract byte[] ReadByteArray(int cnt);
+
+ /// <summary>
+ /// Internal routine to read byte array.
+ /// </summary>
+ /// <param name="len">Array length.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <returns>Byte array</returns>
+ protected byte[] ReadByteArray0(int len, byte* data)
+ {
+ byte[] res = new byte[len];
+
+ fixed (byte* res0 = res)
+ {
+ CopyMemory(data, res0, len);
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Write bool.
+ /// </summary>
+ /// <param name="val">Bool value.</param>
+ public void WriteBool(bool val)
+ {
+ WriteByte(val ? ByteOne : ByteZero);
+ }
+
+ /// <summary>
+ /// Read bool.
+ /// </summary>
+ /// <returns>
+ /// Bool value.
+ /// </returns>
+ public bool ReadBool()
+ {
+ return ReadByte() == ByteOne;
+ }
+
+ /// <summary>
+ /// Write bool array.
+ /// </summary>
+ /// <param name="val">Bool array.</param>
+ public abstract void WriteBoolArray(bool[] val);
+
+ /// <summary>
+ /// Internal routine to write bool array.
+ /// </summary>
+ /// <param name="val">Bool array.</param>
+ /// <param name="data">Data pointer.</param>
+ protected void WriteBoolArray0(bool[] val, byte* data)
+ {
+ fixed (bool* val0 = val)
+ {
+ CopyMemory((byte*)val0, data, val.Length);
+ }
+ }
+
+ /// <summary>
+ /// Read bool array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Bool array.
+ /// </returns>
+ public abstract bool[] ReadBoolArray(int cnt);
+
+ /// <summary>
+ /// Internal routine to read bool array.
+ /// </summary>
+ /// <param name="len">Array length.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <returns>Bool array</returns>
+ protected bool[] ReadBoolArray0(int len, byte* data)
+ {
+ bool[] res = new bool[len];
+
+ fixed (bool* res0 = res)
+ {
+ CopyMemory(data, (byte*)res0, len);
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Write short.
+ /// </summary>
+ /// <param name="val">Short value.</param>
+ public abstract void WriteShort(short val);
+
+ /// <summary>
+ /// Internal routine to write short value.
+ /// </summary>
+ /// <param name="val">Short value.</param>
+ /// <param name="data">Data pointer.</param>
+ protected void WriteShort0(short val, byte* data)
+ {
+ if (LittleEndian)
+ *((short*)data) = val;
+ else
+ {
+ byte* valPtr = (byte*)&val;
+
+ data[0] = valPtr[1];
+ data[1] = valPtr[0];
+ }
+ }
+
+ /// <summary>
+ /// Read short.
+ /// </summary>
+ /// <returns>
+ /// Short value.
+ /// </returns>
+ public abstract short ReadShort();
+
+ /// <summary>
+ /// Internal routine to read short value.
+ /// </summary>
+ /// <param name="data">Data pointer.</param>
+ /// <returns>Short value</returns>
+ protected short ReadShort0(byte* data)
+ {
+ short val;
+
+ if (LittleEndian)
+ val = *((short*)data);
+ else
+ {
+ byte* valPtr = (byte*)&val;
+
+ valPtr[0] = data[1];
+ valPtr[1] = data[0];
+ }
+
+ return val;
+ }
+
+ /// <summary>
+ /// Write short array.
+ /// </summary>
+ /// <param name="val">Short array.</param>
+ public abstract void WriteShortArray(short[] val);
+
+ /// <summary>
+ /// Internal routine to write short array.
+ /// </summary>
+ /// <param name="val">Short array.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ protected void WriteShortArray0(short[] val, byte* data, int cnt)
+ {
+ if (LittleEndian)
+ {
+ fixed (short* val0 = val)
+ {
+ CopyMemory((byte*)val0, data, cnt);
+ }
+ }
+ else
+ {
+ byte* curPos = data;
+
+ for (int i = 0; i < val.Length; i++)
+ {
+ short val0 = val[i];
+
+ byte* valPtr = (byte*)&(val0);
+
+ *curPos++ = valPtr[1];
+ *curPos++ = valPtr[0];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Read short array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Short array.
+ /// </returns>
+ public abstract short[] ReadShortArray(int cnt);
+
+ /// <summary>
+ /// Internal routine to read short array.
+ /// </summary>
+ /// <param name="len">Array length.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ /// <returns>Short array</returns>
+ protected short[] ReadShortArray0(int len, byte* data, int cnt)
+ {
+ short[] res = new short[len];
+
+ if (LittleEndian)
+ {
+ fixed (short* res0 = res)
+ {
+ CopyMemory(data, (byte*)res0, cnt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ short val;
+
+ byte* valPtr = (byte*)&val;
+
+ valPtr[1] = *data++;
+ valPtr[0] = *data++;
+
+ res[i] = val;
+ }
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Write char.
+ /// </summary>
+ /// <param name="val">Char value.</param>
+ public void WriteChar(char val)
+ {
+ WriteShort(*(short*)(&val));
+ }
+
+ /// <summary>
+ /// Read char.
+ /// </summary>
+ /// <returns>
+ /// Char value.
+ /// </returns>
+ public char ReadChar()
+ {
+ short val = ReadShort();
+
+ return *(char*)(&val);
+ }
+
+ /// <summary>
+ /// Write char array.
+ /// </summary>
+ /// <param name="val">Char array.</param>
+ public abstract void WriteCharArray(char[] val);
+
+ /// <summary>
+ /// Internal routine to write char array.
+ /// </summary>
+ /// <param name="val">Char array.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ protected void WriteCharArray0(char[] val, byte* data, int cnt)
+ {
+ if (LittleEndian)
+ {
+ fixed (char* val0 = val)
+ {
+ CopyMemory((byte*)val0, data, cnt);
+ }
+ }
+ else
+ {
+ byte* curPos = data;
+
+ for (int i = 0; i < val.Length; i++)
+ {
+ char val0 = val[i];
+
+ byte* valPtr = (byte*)&(val0);
+
+ *curPos++ = valPtr[1];
+ *curPos++ = valPtr[0];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Read char array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Char array.
+ /// </returns>
+ public abstract char[] ReadCharArray(int cnt);
+
+ /// <summary>
+ /// Internal routine to read char array.
+ /// </summary>
+ /// <param name="len">Count.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ /// <returns>Char array</returns>
+ protected char[] ReadCharArray0(int len, byte* data, int cnt)
+ {
+ char[] res = new char[len];
+
+ if (LittleEndian)
+ {
+ fixed (char* res0 = res)
+ {
+ CopyMemory(data, (byte*)res0, cnt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ char val;
+
+ byte* valPtr = (byte*)&val;
+
+ valPtr[1] = *data++;
+ valPtr[0] = *data++;
+
+ res[i] = val;
+ }
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Write int.
+ /// </summary>
+ /// <param name="val">Int value.</param>
+ public abstract void WriteInt(int val);
+
+ /// <summary>
+ /// Write int to specific position.
+ /// </summary>
+ /// <param name="writePos">Position.</param>
+ /// <param name="val">Value.</param>
+ public abstract void WriteInt(int writePos, int val);
+
+ /// <summary>
+ /// Internal routine to write int value.
+ /// </summary>
+ /// <param name="val">Int value.</param>
+ /// <param name="data">Data pointer.</param>
+ protected void WriteInt0(int val, byte* data)
+ {
+ if (LittleEndian)
+ *((int*)data) = val;
+ else
+ {
+ byte* valPtr = (byte*)&val;
+
+ data[0] = valPtr[3];
+ data[1] = valPtr[2];
+ data[2] = valPtr[1];
+ data[3] = valPtr[0];
+ }
+ }
+
+ /// <summary>
+ /// Read int.
+ /// </summary>
+ /// <returns>
+ /// Int value.
+ /// </returns>
+ public abstract int ReadInt();
+
+ /// <summary>
+ /// Internal routine to read int value.
+ /// </summary>
+ /// <param name="data">Data pointer.</param>
+ /// <returns>Int value</returns>
+ protected int ReadInt0(byte* data) {
+ int val;
+
+ if (LittleEndian)
+ val = *((int*)data);
+ else
+ {
+ byte* valPtr = (byte*)&val;
+
+ valPtr[0] = data[3];
+ valPtr[1] = data[2];
+ valPtr[2] = data[1];
+ valPtr[3] = data[0];
+ }
+
+ return val;
+ }
+
+ /// <summary>
+ /// Write int array.
+ /// </summary>
+ /// <param name="val">Int array.</param>
+ public abstract void WriteIntArray(int[] val);
+
+ /// <summary>
+ /// Internal routine to write int array.
+ /// </summary>
+ /// <param name="val">Int array.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ protected void WriteIntArray0(int[] val, byte* data, int cnt)
+ {
+ if (LittleEndian)
+ {
+ fixed (int* val0 = val)
+ {
+ CopyMemory((byte*)val0, data, cnt);
+ }
+ }
+ else
+ {
+ byte* curPos = data;
+
+ for (int i = 0; i < val.Length; i++)
+ {
+ int val0 = val[i];
+
+ byte* valPtr = (byte*)&(val0);
+
+ *curPos++ = valPtr[3];
+ *curPos++ = valPtr[2];
+ *curPos++ = valPtr[1];
+ *curPos++ = valPtr[0];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Read int array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Int array.
+ /// </returns>
+ public abstract int[] ReadIntArray(int cnt);
+
+ /// <summary>
+ /// Internal routine to read int array.
+ /// </summary>
+ /// <param name="len">Count.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ /// <returns>Int array</returns>
+ protected int[] ReadIntArray0(int len, byte* data, int cnt)
+ {
+ int[] res = new int[len];
+
+ if (LittleEndian)
+ {
+ fixed (int* res0 = res)
+ {
+ CopyMemory(data, (byte*)res0, cnt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ int val;
+
+ byte* valPtr = (byte*)&val;
+
+ valPtr[3] = *data++;
+ valPtr[2] = *data++;
+ valPtr[1] = *data++;
+ valPtr[0] = *data++;
+
+ res[i] = val;
+ }
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Write float.
+ /// </summary>
+ /// <param name="val">Float value.</param>
+ public void WriteFloat(float val)
+ {
+ int val0 = *(int*)(&val);
+
+ WriteInt(val0);
+ }
+
+ /// <summary>
+ /// Read float.
+ /// </summary>
+ /// <returns>
+ /// Float value.
+ /// </returns>
+ public float ReadFloat()
+ {
+ int val = ReadInt();
+
+ return *(float*)(&val);
+ }
+
+ /// <summary>
+ /// Write float array.
+ /// </summary>
+ /// <param name="val">Float array.</param>
+ public abstract void WriteFloatArray(float[] val);
+
+ /// <summary>
+ /// Internal routine to write float array.
+ /// </summary>
+ /// <param name="val">Int array.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ protected void WriteFloatArray0(float[] val, byte* data, int cnt)
+ {
+ if (LittleEndian)
+ {
+ fixed (float* val0 = val)
+ {
+ CopyMemory((byte*)val0, data, cnt);
+ }
+ }
+ else
+ {
+ byte* curPos = data;
+
+ for (int i = 0; i < val.Length; i++)
+ {
+ float val0 = val[i];
+
+ byte* valPtr = (byte*)&(val0);
+
+ *curPos++ = valPtr[3];
+ *curPos++ = valPtr[2];
+ *curPos++ = valPtr[1];
+ *curPos++ = valPtr[0];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Read float array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Float array.
+ /// </returns>
+ public abstract float[] ReadFloatArray(int cnt);
+
+ /// <summary>
+ /// Internal routine to read float array.
+ /// </summary>
+ /// <param name="len">Count.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ /// <returns>Float array</returns>
+ protected float[] ReadFloatArray0(int len, byte* data, int cnt)
+ {
+ float[] res = new float[len];
+
+ if (LittleEndian)
+ {
+ fixed (float* res0 = res)
+ {
+ CopyMemory(data, (byte*)res0, cnt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ int val;
+
+ byte* valPtr = (byte*)&val;
+
+ valPtr[3] = *data++;
+ valPtr[2] = *data++;
+ valPtr[1] = *data++;
+ valPtr[0] = *data++;
+
+ res[i] = val;
+ }
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Write long.
+ /// </summary>
+ /// <param name="val">Long value.</param>
+ public abstract void WriteLong(long val);
+
+ /// <summary>
+ /// Internal routine to write long value.
+ /// </summary>
+ /// <param name="val">Long value.</param>
+ /// <param name="data">Data pointer.</param>
+ protected void WriteLong0(long val, byte* data)
+ {
+ if (LittleEndian)
+ *((long*)data) = val;
+ else
+ {
+ byte* valPtr = (byte*)&val;
+
+ data[0] = valPtr[7];
+ data[1] = valPtr[6];
+ data[2] = valPtr[5];
+ data[3] = valPtr[4];
+ data[4] = valPtr[3];
+ data[5] = valPtr[2];
+ data[6] = valPtr[1];
+ data[7] = valPtr[0];
+ }
+ }
+
+ /// <summary>
+ /// Read long.
+ /// </summary>
+ /// <returns>
+ /// Long value.
+ /// </returns>
+ public abstract long ReadLong();
+
+ /// <summary>
+ /// Internal routine to read long value.
+ /// </summary>
+ /// <param name="data">Data pointer.</param>
+ /// <returns>Long value</returns>
+ protected long ReadLong0(byte* data)
+ {
+ long val;
+
+ if (LittleEndian)
+ val = *((long*)data);
+ else
+ {
+ byte* valPtr = (byte*)&val;
+
+ valPtr[0] = data[7];
+ valPtr[1] = data[6];
+ valPtr[2] = data[5];
+ valPtr[3] = data[4];
+ valPtr[4] = data[3];
+ valPtr[5] = data[2];
+ valPtr[6] = data[1];
+ valPtr[7] = data[0];
+ }
+
+ return val;
+ }
+
+ /// <summary>
+ /// Write long array.
+ /// </summary>
+ /// <param name="val">Long array.</param>
+ public abstract void WriteLongArray(long[] val);
+
+ /// <summary>
+ /// Internal routine to write long array.
+ /// </summary>
+ /// <param name="val">Long array.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ protected void WriteLongArray0(long[] val, byte* data, int cnt)
+ {
+ if (LittleEndian)
+ {
+ fixed (long* val0 = val)
+ {
+ CopyMemory((byte*)val0, data, cnt);
+ }
+ }
+ else
+ {
+ byte* curPos = data;
+
+ for (int i = 0; i < val.Length; i++)
+ {
+ long val0 = val[i];
+
+ byte* valPtr = (byte*)&(val0);
+
+ *curPos++ = valPtr[7];
+ *curPos++ = valPtr[6];
+ *curPos++ = valPtr[5];
+ *curPos++ = valPtr[4];
+ *curPos++ = valPtr[3];
+ *curPos++ = valPtr[2];
+ *curPos++ = valPtr[1];
+ *curPos++ = valPtr[0];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Read long array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Long array.
+ /// </returns>
+ public abstract long[] ReadLongArray(int cnt);
+
+ /// <summary>
+ /// Internal routine to read long array.
+ /// </summary>
+ /// <param name="len">Count.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ /// <returns>Long array</returns>
+ protected long[] ReadLongArray0(int len, byte* data, int cnt)
+ {
+ long[] res = new long[len];
+
+ if (LittleEndian)
+ {
+ fixed (long* res0 = res)
+ {
+ CopyMemory(data, (byte*)res0, cnt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ long val;
+
+ byte* valPtr = (byte*)&val;
+
+ valPtr[7] = *data++;
+ valPtr[6] = *data++;
+ valPtr[5] = *data++;
+ valPtr[4] = *data++;
+ valPtr[3] = *data++;
+ valPtr[2] = *data++;
+ valPtr[1] = *data++;
+ valPtr[0] = *data++;
+
+ res[i] = val;
+ }
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Write double.
+ /// </summary>
+ /// <param name="val">Double value.</param>
+ public void WriteDouble(double val)
+ {
+ long val0 = *(long*)(&val);
+
+ WriteLong(val0);
+ }
+
+ /// <summary>
+ /// Read double.
+ /// </summary>
+ /// <returns>
+ /// Double value.
+ /// </returns>
+ public double ReadDouble()
+ {
+ long val = ReadLong();
+
+ return *(double*)(&val);
+ }
+
+ /// <summary>
+ /// Write double array.
+ /// </summary>
+ /// <param name="val">Double array.</param>
+ public abstract void WriteDoubleArray(double[] val);
+
+ /// <summary>
+ /// Internal routine to write double array.
+ /// </summary>
+ /// <param name="val">Double array.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ protected void WriteDoubleArray0(double[] val, byte* data, int cnt)
+ {
+ if (LittleEndian)
+ {
+ fixed (double* val0 = val)
+ {
+ CopyMemory((byte*)val0, data, cnt);
+ }
+ }
+ else
+ {
+ byte* curPos = data;
+
+ for (int i = 0; i < val.Length; i++)
+ {
+ double val0 = val[i];
+
+ byte* valPtr = (byte*)&(val0);
+
+ *curPos++ = valPtr[7];
+ *curPos++ = valPtr[6];
+ *curPos++ = valPtr[5];
+ *curPos++ = valPtr[4];
+ *curPos++ = valPtr[3];
+ *curPos++ = valPtr[2];
+ *curPos++ = valPtr[1];
+ *curPos++ = valPtr[0];
+ }
+ }
+ }
+
+ /// <summary>
+ /// Read double array.
+ /// </summary>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Double array.
+ /// </returns>
+ public abstract double[] ReadDoubleArray(int cnt);
+
+ /// <summary>
+ /// Internal routine to read double array.
+ /// </summary>
+ /// <param name="len">Count.</param>
+ /// <param name="data">Data pointer.</param>
+ /// <param name="cnt">Bytes count.</param>
+ /// <returns>Double array</returns>
+ protected double[] ReadDoubleArray0(int len, byte* data, int cnt)
+ {
+ double[] res = new double[len];
+
+ if (LittleEndian)
+ {
+ fixed (double* res0 = res)
+ {
+ CopyMemory(data, (byte*)res0, cnt);
+ }
+ }
+ else
+ {
+ for (int i = 0; i < len; i++)
+ {
+ double val;
+
+ byte* valPtr = (byte*)&val;
+
+ valPtr[7] = *data++;
+ valPtr[6] = *data++;
+ valPtr[5] = *data++;
+ valPtr[4] = *data++;
+ valPtr[3] = *data++;
+ valPtr[2] = *data++;
+ valPtr[1] = *data++;
+ valPtr[0] = *data++;
+
+ res[i] = val;
+ }
+ }
+
+ return res;
+ }
+
+ /// <summary>
+ /// Write string.
+ /// </summary>
+ /// <param name="chars">Characters.</param>
+ /// <param name="charCnt">Char count.</param>
+ /// <param name="byteCnt">Byte count.</param>
+ /// <param name="encoding">Encoding.</param>
+ /// <returns>
+ /// Amounts of bytes written.
+ /// </returns>
+ public abstract int WriteString(char* chars, int charCnt, int byteCnt, Encoding encoding);
+
+ /// <summary>
+ /// Internal string write routine.
+ /// </summary>
+ /// <param name="chars">Chars.</param>
+ /// <param name="charCnt">Chars count.</param>
+ /// <param name="byteCnt">Bytes count.</param>
+ /// <param name="enc">Encoding.</param>
+ /// <param name="data">Data.</param>
+ /// <returns>Amount of bytes written.</returns>
+ protected int WriteString0(char* chars, int charCnt, int byteCnt, Encoding enc, byte* data)
+ {
+ return enc.GetBytes(chars, charCnt, data, byteCnt);
+ }
+
+ /// <summary>
+ /// Write arbitrary data.
+ /// </summary>
+ /// <param name="src">Source array.</param>
+ /// <param name="off">Offset</param>
+ /// <param name="cnt">Count.</param>
+ public void Write(byte[] src, int off, int cnt)
+ {
+ fixed (byte* src0 = src)
+ {
+ Write(src0 + off, cnt);
+ }
+ }
+
+ /// <summary>
+ /// Read arbitrary data.
+ /// </summary>
+ /// <param name="dest">Destination array.</param>
+ /// <param name="off">Offset.</param>
+ /// <param name="cnt">Count.</param>
+ /// <returns>
+ /// Amount of bytes read.
+ /// </returns>
+ public void Read(byte[] dest, int off, int cnt)
+ {
+ fixed (byte* dest0 = dest)
+ {
+ Read(dest0 + off, cnt);
+ }
+ }
+
+ /// <summary>
+ /// Write arbitrary data.
+ /// </summary>
+ /// <param name="src">Source.</param>
+ /// <param name="cnt">Count.</param>
+ public abstract void Write(byte* src, int cnt);
+
+ /// <summary>
+ /// Internal write routine.
+ /// </summary>
+ /// <param name="src">Source.</param>
+ /// <param name="cnt">Count.</param>
+ /// <param name="data">Data (dsetination).</param>
+ protected void WriteInternal(byte* src, int cnt, byte* data)
+ {
+ CopyMemory(src, data + Pos, cnt);
+ }
+
+ /// <summary>
+ /// Read arbitrary data.
+ /// </summary>
+ /// <param name="dest">Destination.</param>
+ /// <param name="cnt">Count.</param>
+ /// <returns></returns>
+ public abstract void Read(byte* dest, int cnt);
+
+ /// <summary>
+ /// Internal read routine.
+ /// </summary>
+ /// <param name="dest">Destination.</param>
+ /// <param name="cnt">Count.</param>
+ /// <param name="data">Data (source).</param>
+ /// <returns>Amount of bytes written.</returns>
+ protected void ReadInternal(byte* dest, int cnt, byte* data)
+ {
+ int cnt0 = Math.Min(Remaining(), cnt);
+
+ CopyMemory(data + Pos, dest, cnt0);
+
+ ShiftRead(cnt0);
+ }
+
+ /// <summary>
+ /// Position.
+ /// </summary>
+ public int Position
+ {
+ get { return Pos; }
+ }
+
+ /// <summary>
+ /// Gets remaining bytes in the stream.
+ /// </summary>
+ /// <returns>
+ /// Remaining bytes.
+ /// </returns>
+ public abstract int Remaining();
+
+ /// <summary>
+ /// Gets underlying array, avoiding copying if possible.
+ /// </summary>
+ /// <returns>
+ /// Underlying array.
+ /// </returns>
+ public abstract byte[] Array();
+
+ /// <summary>
+ /// Gets underlying data in a new array.
+ /// </summary>
+ /// <returns>
+ /// New array with data.
+ /// </returns>
+ public abstract byte[] ArrayCopy();
+
+ /// <summary>
+ /// Check whether array passed as argument is the same as the stream hosts.
+ /// </summary>
+ /// <param name="arr">Array.</param>
+ /// <returns>
+ /// <c>True</c> if they are same.
+ /// </returns>
+ public virtual bool IsSameArray(byte[] arr)
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Seek to the given positoin.
+ /// </summary>
+ /// <param name="offset">Offset.</param>
+ /// <param name="origin">Seek origin.</param>
+ /// <returns>
+ /// Position.
+ /// </returns>
+ /// <exception cref="System.ArgumentException">
+ /// Unsupported seek origin: + origin
+ /// or
+ /// Seek before origin: + newPos
+ /// </exception>
+ public int Seek(int offset, SeekOrigin origin)
+ {
+ int newPos;
+
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+ {
+ newPos = offset;
+
+ break;
+ }
+
+ case SeekOrigin.Current:
+ {
+ newPos = Pos + offset;
+
+ break;
+ }
+
+ default:
+ throw new ArgumentException("Unsupported seek origin: " + origin);
+ }
+
+ if (newPos < 0)
+ throw new ArgumentException("Seek before origin: " + newPos);
+
+ EnsureWriteCapacity(newPos);
+
+ Pos = newPos;
+
+ return Pos;
+ }
+
+ /** <inheritdoc /> */
+ public void Dispose()
+ {
+ if (_disposed)
+ return;
+
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+
+ _disposed = true;
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ protected abstract void Dispose(bool disposing);
+
+ /// <summary>
+ /// Ensure capacity for write.
+ /// </summary>
+ /// <param name="cnt">Bytes count.</param>
+ protected abstract void EnsureWriteCapacity(int cnt);
+
+ /// <summary>
+ /// Ensure capacity for write and shift position.
+ /// </summary>
+ /// <param name="cnt">Bytes count.</param>
+ /// <returns>Position before shift.</returns>
+ protected int EnsureWriteCapacityAndShift(int cnt)
+ {
+ int pos0 = Pos;
+
+ EnsureWriteCapacity(Pos + cnt);
+
+ ShiftWrite(cnt);
+
+ return pos0;
+ }
+
+ /// <summary>
+ /// Ensure capacity for read.
+ /// </summary>
+ /// <param name="cnt">Bytes count.</param>
+ protected abstract void EnsureReadCapacity(int cnt);
+
+ /// <summary>
+ /// Ensure capacity for read and shift position.
+ /// </summary>
+ /// <param name="cnt">Bytes count.</param>
+ /// <returns>Position before shift.</returns>
+ protected int EnsureReadCapacityAndShift(int cnt)
+ {
+ int pos0 = Pos;
+
+ EnsureReadCapacity(cnt);
+
+ ShiftRead(cnt);
+
+ return pos0;
+ }
+
+ /// <summary>
+ /// Shift position due to write
+ /// </summary>
+ /// <param name="cnt">Bytes count.</param>
+ protected void ShiftWrite(int cnt)
+ {
+ Pos += cnt;
+ }
+
+ /// <summary>
+ /// Shift position due to read.
+ /// </summary>
+ /// <param name="cnt">Bytes count.</param>
+ protected void ShiftRead(int cnt)
+ {
+ Pos += cnt;
+ }
+
+ /// <summary>
+ /// Calculate new capacity.
+ /// </summary>
+ /// <param name="curCap">Current capacity.</param>
+ /// <param name="reqCap">Required capacity.</param>
+ /// <returns>New capacity.</returns>
+ protected static int Capacity(int curCap, int reqCap)
+ {
+ int newCap;
+
+ if (reqCap < 256)
+ newCap = 256;
+ else
+ {
+ newCap = curCap << 1;
+
+ if (newCap < reqCap)
+ newCap = reqCap;
+ }
+
+ return newCap;
+ }
+
+ /// <summary>
+ /// Unsafe memory copy routine.
+ /// </summary>
+ /// <param name="src">Source.</param>
+ /// <param name="dest">Destination.</param>
+ /// <param name="len">Length.</param>
+ public static void CopyMemory(byte* src, byte* dest, int len)
+ {
+ if (MemcpyInverted)
+ Memcpy.Invoke(dest, src, len);
+ else
+ Memcpy.Invoke(src, dest, len);
+ }
+ }
+}