mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/PCK-Studio.git
synced 2026-07-08 17:09:30 +00:00
Add GRFFile class and GRFFileReader
This commit is contained in:
246
MinecraftUSkinEditor/Classes/FileTypes/GRFFile.cs
Normal file
246
MinecraftUSkinEditor/Classes/FileTypes/GRFFile.cs
Normal file
@@ -0,0 +1,246 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PckStudio.Classes.FileTypes
|
||||
{
|
||||
public class GRFFile
|
||||
{
|
||||
|
||||
public GRFTag RootTag = null;
|
||||
public int Crc => _crc;
|
||||
public eCompressionType CompressionType => _compressionType;
|
||||
|
||||
private int _crc = 0;
|
||||
private eCompressionType _compressionType = eCompressionType.None;
|
||||
|
||||
[Flags]
|
||||
public enum eCompressionType : byte
|
||||
{
|
||||
None = 0,
|
||||
Zlib = 1,
|
||||
ZlibRle = 2,
|
||||
/// <summary>
|
||||
/// custom enum value
|
||||
/// </summary>
|
||||
IsWolrdGrf = 0x80,
|
||||
}
|
||||
|
||||
public class GRFTag
|
||||
{
|
||||
private GRFTag _parent = null;
|
||||
private SortedDictionary<string, string> _parameters = new SortedDictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Contains all valid Parameter names
|
||||
/// </summary>
|
||||
public static readonly string[] ValidParameters = new string[]
|
||||
{
|
||||
"plus_x",
|
||||
"minus_x",
|
||||
"plus_z",
|
||||
"minus_z",
|
||||
"omni_plus_x",
|
||||
"omni_minus_x",
|
||||
"omni_plus_z",
|
||||
"omni_minus_z",
|
||||
"none",
|
||||
"plus_y",
|
||||
"minus_y",
|
||||
"plus_x",
|
||||
"minus_x",
|
||||
"plus_z",
|
||||
"minus_z",
|
||||
"descriptionName",
|
||||
"promptName",
|
||||
"dataTag",
|
||||
"enchantmentId",
|
||||
"enchantmentLevel",
|
||||
"itemId",
|
||||
"quantity",
|
||||
"auxValue",
|
||||
"slot",
|
||||
"name",
|
||||
"food",
|
||||
"health",
|
||||
"blockId",
|
||||
"useCoords",
|
||||
"seed",
|
||||
"flatworld",
|
||||
"filename",
|
||||
"rot",
|
||||
"data",
|
||||
"block",
|
||||
"entity",
|
||||
"facing",
|
||||
"edgeBlock",
|
||||
"fillBlock",
|
||||
"skipAir",
|
||||
"x",
|
||||
"x0",
|
||||
"x1",
|
||||
"y",
|
||||
"y0",
|
||||
"y1",
|
||||
"z",
|
||||
"z0",
|
||||
"z1",
|
||||
"chunkX",
|
||||
"chunkZ",
|
||||
"yRot",
|
||||
"xRot",
|
||||
"spawnX",
|
||||
"spawnY",
|
||||
"spawnZ",
|
||||
"orientation",
|
||||
"dimension",
|
||||
"topblockId",
|
||||
"biomeId",
|
||||
"feature",
|
||||
"minCount",
|
||||
"maxCount",
|
||||
"weight",
|
||||
"id",
|
||||
"probability",
|
||||
"method",
|
||||
"hasBeenInCreative",
|
||||
"cloudHeight",
|
||||
"fogDistance",
|
||||
"dayTime",
|
||||
"target",
|
||||
"speed",
|
||||
"dir",
|
||||
"type",
|
||||
"pass",
|
||||
"for",
|
||||
"random",
|
||||
"blockAux",
|
||||
"size",
|
||||
"scale",
|
||||
"freq",
|
||||
"func",
|
||||
"upper",
|
||||
"lower",
|
||||
"dY",
|
||||
"thickness",
|
||||
"points",
|
||||
"holeSize",
|
||||
"variant",
|
||||
"startHeight",
|
||||
"pattern",
|
||||
"colour",
|
||||
"primary",
|
||||
"laps",
|
||||
"liftForceModifier",
|
||||
"staticLift",
|
||||
"targetHeight",
|
||||
"speedBoost",
|
||||
"boostDirection",
|
||||
"condition_type",
|
||||
"condition_value_0",
|
||||
"condition_value_1",
|
||||
"beam_length",
|
||||
};
|
||||
|
||||
public static readonly string[] ValidGameRules = new string[]
|
||||
{
|
||||
"MapOptions",
|
||||
"ApplySchematic",
|
||||
"GenerateStructure",
|
||||
"GenerateBox",
|
||||
"PlaceBlock",
|
||||
"PlaceContainer",
|
||||
"PlaceSpawner",
|
||||
"BiomeOverride",
|
||||
"StartFeature",
|
||||
"AddItem",
|
||||
"AddEnchantment",
|
||||
"WeighedTreasureItem",
|
||||
"RandomItemSet",
|
||||
"DistributeItems",
|
||||
"WorldPosition",
|
||||
"LevelRules",
|
||||
"NamedArea",
|
||||
"ActiveChunkArea",
|
||||
"TargetArea",
|
||||
"ScoreRing",
|
||||
"ThermalArea",
|
||||
"PlayerBoundsVolume",
|
||||
"Killbox",
|
||||
"BlockLayer",
|
||||
"UseBlock",
|
||||
"CollectItem",
|
||||
"CompleteAll",
|
||||
"UpdatePlayer",
|
||||
"OnGameStartSpawnPositions",
|
||||
"OnInitialiseWorld",
|
||||
"SpawnPositionSet",
|
||||
"PopulateContainer",
|
||||
"DegradationSequence",
|
||||
"RandomDissolveDegrade",
|
||||
"DirectionalDegrade",
|
||||
"GrantPermissions",
|
||||
"AllowIn",
|
||||
"LayerGeneration",
|
||||
"LayerAsset",
|
||||
"AnyCombinationOf",
|
||||
"CombinationDefinition",
|
||||
"Variations",
|
||||
"BlockDef",
|
||||
"LayerSize",
|
||||
"UniformSize",
|
||||
"RandomizeSize",
|
||||
"LinearBlendSize",
|
||||
"LayerShape",
|
||||
"BasicShape",
|
||||
"StarShape",
|
||||
"PatchyShape",
|
||||
"RingShape",
|
||||
"SpiralShape",
|
||||
"LayerFill",
|
||||
"BasicLayerFill",
|
||||
"CurvedLayerFill",
|
||||
"WarpedLayerFill",
|
||||
"LayerTheme",
|
||||
"NullTheme",
|
||||
"FilterTheme",
|
||||
"ShaftsTheme",
|
||||
"BasicPatchesTheme",
|
||||
"BlockStackTheme",
|
||||
"RainbowTheme",
|
||||
"TerracottaTheme",
|
||||
"FunctionPatchesTheme",
|
||||
"SimplePatchesTheme",
|
||||
"CarpetTrapTheme",
|
||||
"MushroomBlockTheme",
|
||||
"TextureTheme",
|
||||
"SchematicTheme",
|
||||
"BlockCollisionException",
|
||||
"Powerup",
|
||||
"Checkpoint",
|
||||
"CustomBeacon",
|
||||
"ActiveViewArea",
|
||||
};
|
||||
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public GRFTag Parent => _parent;
|
||||
public SortedDictionary<string, string> Parameters => _parameters;
|
||||
public List<GRFTag> Tags { get; set; } = new List<GRFTag>();
|
||||
|
||||
public GRFTag(string name, GRFTag parent)
|
||||
{
|
||||
Name = name;
|
||||
_parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
public GRFFile(eCompressionType compressionType, int crc)
|
||||
{
|
||||
_compressionType = compressionType;
|
||||
_crc = crc;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
168
MinecraftUSkinEditor/Classes/IO/GRF/GRFFileReader.cs
Normal file
168
MinecraftUSkinEditor/Classes/IO/GRF/GRFFileReader.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using PckStudio.Classes.FileTypes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
|
||||
using PckStudio.Classes.Utils;
|
||||
|
||||
namespace PckStudio.Classes.IO.GRF
|
||||
{
|
||||
internal class GRFFileReader
|
||||
{
|
||||
internal List<string> TagNames;
|
||||
internal GRFFile _file;
|
||||
public static GRFFile Read(Stream stream)
|
||||
{
|
||||
return new GRFFileReader().read(stream);
|
||||
}
|
||||
|
||||
|
||||
private GRFFile read(Stream stream)
|
||||
{
|
||||
stream = ReadHeader(stream);
|
||||
ReadTagNames(stream);
|
||||
ReadGRFTags(stream);
|
||||
return _file;
|
||||
}
|
||||
|
||||
|
||||
private Stream ReadHeader(Stream stream)
|
||||
{
|
||||
int x = ReadShort(stream);
|
||||
if (((x >> 31) | x) == 0)
|
||||
{
|
||||
ReadBytes(stream, 14); // 14 bools ?...
|
||||
return stream;
|
||||
}
|
||||
|
||||
GRFFile.eCompressionType compression_type = (GRFFile.eCompressionType)stream.ReadByte();
|
||||
int crc = ReadInt(stream);
|
||||
int byte1 = stream.ReadByte();
|
||||
int byte2 = stream.ReadByte();
|
||||
int byte3 = stream.ReadByte();
|
||||
int byte4 = stream.ReadByte();
|
||||
if (byte4 > 0)
|
||||
{
|
||||
compression_type = (GRFFile.eCompressionType)byte4;
|
||||
// Custom enum
|
||||
compression_type &= GRFFile.eCompressionType.IsWolrdGrf;
|
||||
}
|
||||
_file = new GRFFile(compression_type, crc);
|
||||
|
||||
if (compression_type == GRFFile.eCompressionType.None && byte4 == 0)
|
||||
return stream;
|
||||
|
||||
int buf_size = ReadInt(stream);
|
||||
if (byte4 != 0)
|
||||
{
|
||||
stream = new MemoryStream(ReadBytes(stream, buf_size));
|
||||
buf_size = ReadInt(stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReadInt(stream); // ignored cuz rest of data is compressed
|
||||
}
|
||||
stream = DecompressZLX(stream);
|
||||
if (compression_type > GRFFile.eCompressionType.Zlib)
|
||||
{
|
||||
byte[] data = RLE<byte>.Decode(ReadBytes(stream, buf_size)).ToArray();
|
||||
stream = new MemoryStream(data);
|
||||
}
|
||||
|
||||
if (byte4 != 0)
|
||||
ReadBytes(stream, 23);
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
private Stream DecompressZLX(Stream compressedStream)
|
||||
{
|
||||
Stream outputstream = new MemoryStream();
|
||||
using (var inputStream = new InflaterInputStream(compressedStream))
|
||||
{
|
||||
inputStream.CopyTo(outputstream);
|
||||
outputstream.Position = 0;
|
||||
};
|
||||
return outputstream;
|
||||
}
|
||||
|
||||
private void ReadTagNames(Stream stream)
|
||||
{
|
||||
int name_count = ReadInt(stream);
|
||||
TagNames = new List<string>(name_count);
|
||||
for (int i = 0; i < name_count; i++)
|
||||
TagNames.Add(ReadString(stream));
|
||||
}
|
||||
|
||||
private void ReadGRFTags(Stream stream)
|
||||
{
|
||||
var NameAndCount = GetTagNameAndDetailCount(stream);
|
||||
_file.RootTag = new GRFFile.GRFTag(NameAndCount.Item1, null);
|
||||
_file.RootTag.Tags = ReadItemList(stream, NameAndCount.Item2, _file.RootTag);
|
||||
}
|
||||
|
||||
internal List<GRFFile.GRFTag> ReadItemList(Stream stream, int count, GRFFile.GRFTag parent)
|
||||
{
|
||||
List<GRFFile.GRFTag> tags = new List<GRFFile.GRFTag>();
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var valuePair = GetTagNameAndDetailCount(stream);
|
||||
var tag = new GRFFile.GRFTag(valuePair.Item1, parent);
|
||||
for (var j = 0; j < valuePair.Item2; j++)
|
||||
{
|
||||
var tuple = GetTagNameAndValue(stream);
|
||||
tag.Parameters.Add(tuple.Item1, tuple.Item2);
|
||||
}
|
||||
tag.Tags = ReadItemList(stream, ReadInt(stream), tag);
|
||||
tags.Add(tag);
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
internal string GetTagName(Stream stream) => TagNames[ReadInt(stream)];
|
||||
|
||||
internal (string, int) GetTagNameAndDetailCount(Stream stream)
|
||||
{
|
||||
return new ValueTuple<string, int>(GetTagName(stream), ReadInt(stream));
|
||||
}
|
||||
|
||||
internal (string, string) GetTagNameAndValue(Stream stream)
|
||||
{
|
||||
return new ValueTuple<string, string>(GetTagName(stream), ReadString(stream));
|
||||
}
|
||||
|
||||
internal byte[] ReadBytes(Stream stream, int count)
|
||||
{
|
||||
byte[] buffer = new byte[count];
|
||||
stream.Read(buffer, 0, count);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
internal int ReadInt(Stream stream)
|
||||
{
|
||||
byte[] buffer = ReadBytes(stream, 4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToInt32(buffer, 0);
|
||||
}
|
||||
|
||||
internal short ReadShort(Stream stream)
|
||||
{
|
||||
byte[] buffer = ReadBytes(stream, 2);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToInt16(buffer, 0);
|
||||
}
|
||||
|
||||
internal string ReadString(Stream stream)
|
||||
{
|
||||
short stringLength = ReadShort(stream);
|
||||
byte[] buffer = ReadBytes(stream, stringLength);
|
||||
return Encoding.UTF8.GetString(buffer);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
92
MinecraftUSkinEditor/Classes/IO/GRF/GRFFileWriter.cs
Normal file
92
MinecraftUSkinEditor/Classes/IO/GRF/GRFFileWriter.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using PckStudio.Classes.FileTypes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace PckStudio.Classes.IO.GRF
|
||||
{
|
||||
public class GRFFileWriter
|
||||
{
|
||||
internal GRFFile _grfFile;
|
||||
public static void Write(Stream stream, GRFFile grfFile)
|
||||
{
|
||||
new GRFFileWriter(grfFile).write(stream);
|
||||
}
|
||||
|
||||
private GRFFileWriter(GRFFile grfFile)
|
||||
{
|
||||
_grfFile = grfFile;
|
||||
}
|
||||
|
||||
private void write(Stream stream)
|
||||
{
|
||||
BuildHeader(stream);
|
||||
WriteTagNames(stream);
|
||||
}
|
||||
|
||||
|
||||
private void BuildHeader(Stream stream)
|
||||
{
|
||||
WriteShort(stream, 1); // (x >> 31 | x) == 1
|
||||
stream.WriteByte((byte)_grfFile.CompressionType);
|
||||
WriteInt(stream, _grfFile.Crc);
|
||||
stream.WriteByte(0);
|
||||
stream.WriteByte(0);
|
||||
stream.WriteByte(0);
|
||||
stream.WriteByte(0);
|
||||
}
|
||||
|
||||
private void WriteTagNames(Stream stream)
|
||||
{
|
||||
List<string> tagNames = new List<string>();
|
||||
GatherTagNames(_grfFile.RootTag, tagNames);
|
||||
WriteInt(stream, tagNames.Count);
|
||||
foreach (var s in tagNames)
|
||||
{
|
||||
WriteString(stream, s);
|
||||
Console.WriteLine(s);
|
||||
}
|
||||
}
|
||||
|
||||
private void GatherTagNames(GRFFile.GRFTag tag, List<string> l)
|
||||
{
|
||||
if (!l.Contains(tag.Name)) l.Add(tag.Name);
|
||||
foreach (var subTag in tag.Tags)
|
||||
GatherTagNames(subTag, l);
|
||||
foreach (var subTag in tag.Parameters)
|
||||
if (!l.Contains(subTag.Key)) l.Add(subTag.Key);
|
||||
}
|
||||
|
||||
internal void WriteInt(Stream stream, int value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes);
|
||||
WriteBytes(stream, bytes);
|
||||
}
|
||||
|
||||
internal void WriteShort(Stream stream, short value)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(value);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
Array.Reverse(bytes);
|
||||
WriteBytes(stream, bytes);
|
||||
}
|
||||
|
||||
internal void WriteString(Stream stream, string s)
|
||||
{
|
||||
WriteShort(stream, (short)s.Length);
|
||||
WriteBytes(stream, Encoding.UTF8.GetBytes(s));
|
||||
}
|
||||
|
||||
internal void WriteBytes(Stream stream, byte[] bytes)
|
||||
{
|
||||
stream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
215
MinecraftUSkinEditor/Classes/Utils/RLE.cs
Normal file
215
MinecraftUSkinEditor/Classes/Utils/RLE.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
namespace PckStudio.Classes.Utils;
|
||||
|
||||
///! Credits
|
||||
///! <see cref="https://nicoschertler.wordpress.com/2014/06/04/generic-run-length-encoding-rle-for-c/"/>
|
||||
|
||||
/// <summary>
|
||||
/// Provides the RLE codec for any integer data type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data's type. Must be an integer type or an ArgumentException will be thrown</typeparam>
|
||||
static class RLE<T> where T : struct, IConvertible
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the marker that identifies a compressed run
|
||||
/// </summary>
|
||||
private static T rleMarker;
|
||||
|
||||
/// <summary>
|
||||
/// A run can be at most as long as the marker - 1
|
||||
/// </summary>
|
||||
private static ulong maxLength;
|
||||
|
||||
static RLE()
|
||||
{
|
||||
GetMaxValues();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RLE-Encodes a data set.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to encode</param>
|
||||
/// <returns>Encoded data</returns>
|
||||
public static IEnumerable<T> Encode(IEnumerable<T> data)
|
||||
{
|
||||
var enumerator = data.GetEnumerator();
|
||||
|
||||
if (!enumerator.MoveNext())
|
||||
yield break;
|
||||
|
||||
var firstRunValue = enumerator.Current;
|
||||
ulong runLength = 1;
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
var currentValue = enumerator.Current;
|
||||
// if the current value is the value of the current run, don't yield anything,
|
||||
// just extend the run
|
||||
if (currentValue.Equals(firstRunValue))
|
||||
runLength++;
|
||||
else
|
||||
{
|
||||
// the current value is different from the current run
|
||||
// yield what we have so far
|
||||
foreach (var item in MakeRun(firstRunValue, runLength))
|
||||
yield return item;
|
||||
|
||||
// and reset the run
|
||||
firstRunValue = currentValue;
|
||||
runLength = 1;
|
||||
}
|
||||
// if there are very many identical values, don't exceed the max length
|
||||
if (runLength > maxLength)
|
||||
{
|
||||
foreach (var item in MakeRun(firstRunValue, maxLength))
|
||||
yield return item;
|
||||
runLength -= maxLength;
|
||||
}
|
||||
}
|
||||
//yield everything that has been buffered
|
||||
foreach (var item in MakeRun(firstRunValue, runLength))
|
||||
yield return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes RLE-encoded data
|
||||
/// </summary>
|
||||
/// <param name="data">RLE-encoded data</param>
|
||||
/// <returns>The original data</returns>
|
||||
public static IEnumerable<T> Decode(IEnumerable<T> data)
|
||||
{
|
||||
var enumerator = data.GetEnumerator();
|
||||
if (!enumerator.MoveNext())
|
||||
yield break;
|
||||
|
||||
do
|
||||
{
|
||||
var value = enumerator.Current;
|
||||
if (!value.Equals(rleMarker))
|
||||
{
|
||||
//an ordinary value
|
||||
yield return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
//might be flag or escape
|
||||
//examine the next value
|
||||
if (!enumerator.MoveNext())
|
||||
throw new ArgumentException("The provided data is not properly encoded.");
|
||||
if (enumerator.Current.Equals(rleMarker))
|
||||
{
|
||||
//escaped value
|
||||
yield return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
//rle marker
|
||||
var length = enumerator.Current.ToInt64(CultureInfo.InvariantCulture);
|
||||
if (!enumerator.MoveNext())
|
||||
throw new ArgumentException("The provided data is not properly encoded.");
|
||||
var val = enumerator.Current;
|
||||
for (var j = 0; j < length+1; ++j)
|
||||
yield return val;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (enumerator.MoveNext());
|
||||
}
|
||||
|
||||
private static IEnumerable<T> MakeRun(T value, ulong length)
|
||||
{
|
||||
if ((length <= 3 && !value.Equals(rleMarker)) || length <= 1)
|
||||
{
|
||||
//don't compress this run, it is just too small
|
||||
for (ulong i = 0; i < length; ++i)
|
||||
{
|
||||
if (value.Equals(rleMarker))
|
||||
yield return rleMarker;
|
||||
yield return value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//compressed run
|
||||
yield return rleMarker;
|
||||
yield return (T)(dynamic)length;
|
||||
yield return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void GetMaxValues()
|
||||
{
|
||||
object maxValue = default(T);
|
||||
TypeCode typeCode = Type.GetTypeCode(typeof(T));
|
||||
switch (typeCode)
|
||||
{
|
||||
case TypeCode.Byte:
|
||||
{
|
||||
var limit = byte.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
case TypeCode.Char:
|
||||
{
|
||||
var limit = char.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
case TypeCode.Int16:
|
||||
{
|
||||
var limit = short.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
case TypeCode.Int32:
|
||||
{
|
||||
var limit = int.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
case TypeCode.Int64:
|
||||
{
|
||||
var limit = long.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
case TypeCode.SByte:
|
||||
{
|
||||
var limit = sbyte.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
case TypeCode.UInt16:
|
||||
{
|
||||
var limit = ushort.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
case TypeCode.UInt32:
|
||||
{
|
||||
var limit = uint.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
case TypeCode.UInt64:
|
||||
{
|
||||
var limit = ulong.MaxValue;
|
||||
rleMarker = __refvalue(__makeref(limit), T);
|
||||
maxLength = (ulong)(limit - 1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentException("The provided type parameter is not an integer type");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user