C# CircularBuffer how to understand readOffset & mCapacityMask - c#

I saw a script about CircularBuffer.cs,and i can not understand a case.
This is the whole program:
The case that i can not underatand is " readOffset & mCapacityMask" in function Peek and Write.
I know the result of " readOffset & mCapacityMask ",but i do not know that why the operate can get that reault.
internal class CircularBuffer
{
private byte[] mBuffer = null;
private int mCapacity = 0;
private int mCapacityMask = 0;
private int mHead = 0;
private int mTail = 0;
private int PowerOfTwo(int e)
{
if (e == 0)
return 1;
return 2 * (PowerOfTwo(e - 1));
}
public CircularBuffer(int capacityPower)
{
mCapacity = PowerOfTwo(capacityPower);
mCapacityMask = mCapacity - 1;
mBuffer = new byte[mCapacity];
}
public WeakReference GetBuffer()
{
return new WeakReference(mBuffer, false);
}
public int GetStoredSize()
{
if (mHead > mTail)
{
return mHead - mTail;
}
else if (mHead < mTail)
{
return (mCapacity - mTail) + mHead;
}
return 0;
}
public bool Peek(byte[] destBuf, int bytes)
{
if (bytes > GetStoredSize())
return false;
int readOffset = mTail + bytes;
int afterReadBytes = readOffset > mCapacity ? readOffset & mCapacityMask : 0;
int readBytes = bytes - afterReadBytes;
Buffer.BlockCopy(mBuffer, mTail, destBuf, 0, readBytes);
if (afterReadBytes > 0)
{
Buffer.BlockCopy(mBuffer, 0, destBuf, readBytes, afterReadBytes);
}
return true;
}
public bool Read(byte[] destBuf, int bytes)
{
if (bytes > GetStoredSize())
return false;
int readOffset = mTail + bytes;
int afterReadBytes = readOffset > mCapacity ? readOffset & mCapacityMask : 0;
int readBytes = bytes - afterReadBytes;
Buffer.BlockCopy(mBuffer, mTail, destBuf, 0, readBytes);
if (afterReadBytes > 0)
{
Buffer.BlockCopy(mBuffer, 0, destBuf, readBytes, afterReadBytes);
}
mTail = readOffset & mCapacityMask;
return true;
}
public bool Write(byte[] data, int offset, int bytes)
{
if (mCapacity < GetStoredSize() + bytes)
{
return false;
}
int writeOffset = mHead + bytes;
int afterWriteBytes = writeOffset > mCapacity ? writeOffset & mCapacityMask : 0;
int writeBytes = bytes - afterWriteBytes;
Buffer.BlockCopy(data, offset, mBuffer, mHead, writeBytes);
if (afterWriteBytes > 0)
{
Buffer.BlockCopy(data, offset + writeBytes, mBuffer, 0, afterWriteBytes);
}
mHead = writeOffset & mCapacityMask;
return true;
}
public bool Remove(int bytes)
{
if (bytes > GetStoredSize())
return false;
mTail = (mTail + bytes) & mCapacityMask;
return true;
}
public void Clear()
{
mHead = 0;
mTail = 0;
}
}

Related

Implement Downloading Large files > 2gb in ASP.NET Core

This is my code:
var net = new System.Net.WebClient();
var data = net.DownloadData(zipPath);
var content = new MemoryStream(data);
var contentType = "APPLICATION/octet-stream";
var fileName = zipPath.Split('\\')[zipPath.Split('\\').Length -1];
Response.Cookies.Append("download", "finished");
return File(content, contentType, fileName);
However, DownloadData(zipPath) gives error as WebException: "The message length limit was exceeded"
it seems like it can't read more than 2GB of size, I searched and it needs to edit some property to -1 of an object which i didn't use in my code.. https://social.msdn.microsoft.com/Forums/en-US/88d0c0bb-ec86-435d-9d2a-c5ec821e9a79/httpwebresponse-maximum-response-header-size-response-over-64k-problem?forum=winappswithcsharp
and I have tried this aswell:
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(zipPath, FileMode.Open, FileAccess.Read);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
Gave this exception: System.IO.IOException: 'The file is too long. This operation is currently limited to supporting files less than 2 gigabytes in size.'
I don't know what to do anymore.. any advice?
In the end i'm trying to return File(byte[]) so I could download that file from the server.
Thanks for everyone who tried helping me, I have found the solution myself after digging hard in the documentation and re checking answers, combining ideas, etc..
You got two solutions:
1- Make a class that implements Stream as a HugeMemoryStream, Which of course you can find here:
class HugeMemoryStream : System.IO.Stream
{
#region Fields
private const int PAGE_SIZE = 1024000000;
private const int ALLOC_STEP = 1024;
private byte[][] _streamBuffers;
private int _pageCount = 0;
private long _allocatedBytes = 0;
private long _position = 0;
private long _length = 0;
#endregion Fields
#region Internals
private int GetPageCount(long length)
{
int pageCount = (int)(length / PAGE_SIZE) + 1;
if ((length % PAGE_SIZE) == 0)
pageCount--;
return pageCount;
}
private void ExtendPages()
{
if (_streamBuffers == null)
{
_streamBuffers = new byte[ALLOC_STEP][];
}
else
{
byte[][] streamBuffers = new byte[_streamBuffers.Length + ALLOC_STEP][];
Array.Copy(_streamBuffers, streamBuffers, _streamBuffers.Length);
_streamBuffers = streamBuffers;
}
_pageCount = _streamBuffers.Length;
}
private void AllocSpaceIfNeeded(long value)
{
if (value < 0)
throw new InvalidOperationException("AllocSpaceIfNeeded < 0");
if (value == 0)
return;
int currentPageCount = GetPageCount(_allocatedBytes);
int neededPageCount = GetPageCount(value);
while (currentPageCount < neededPageCount)
{
if (currentPageCount == _pageCount)
ExtendPages();
_streamBuffers[currentPageCount++] = new byte[PAGE_SIZE];
}
_allocatedBytes = (long)currentPageCount * PAGE_SIZE;
value = Math.Max(value, _length);
if (_position > (_length = value))
_position = _length;
}
#endregion Internals
#region Stream
public override bool CanRead => true;
public override bool CanSeek => true;
public override bool CanWrite => true;
public override long Length => _length;
public override long Position
{
get { return _position; }
set
{
if (value > _length)
throw new InvalidOperationException("Position > Length");
else if (value < 0)
throw new InvalidOperationException("Position < 0");
else
_position = value;
}
}
public override void Flush() { }
public override int Read(byte[] buffer, int offset, int count)
{
int currentPage = (int)(_position / PAGE_SIZE);
int currentOffset = (int)(_position % PAGE_SIZE);
int currentLength = PAGE_SIZE - currentOffset;
long startPosition = _position;
if (startPosition + count > _length)
count = (int)(_length - startPosition);
while (count != 0 && _position < _length)
{
if (currentLength > count)
currentLength = count;
Array.Copy(_streamBuffers[currentPage++], currentOffset, buffer, offset, currentLength);
offset += currentLength;
_position += currentLength;
count -= currentLength;
currentOffset = 0;
currentLength = PAGE_SIZE;
}
return (int)(_position - startPosition);
}
public override long Seek(long offset, SeekOrigin origin)
{
switch (origin)
{
case SeekOrigin.Begin:
break;
case SeekOrigin.Current:
offset += _position;
break;
case SeekOrigin.End:
offset = _length - offset;
break;
default:
throw new ArgumentOutOfRangeException("origin");
}
return Position = offset;
}
public override void SetLength(long value)
{
if (value < 0)
throw new InvalidOperationException("SetLength < 0");
if (value == 0)
{
_streamBuffers = null;
_allocatedBytes = _position = _length = 0;
_pageCount = 0;
return;
}
int currentPageCount = GetPageCount(_allocatedBytes);
int neededPageCount = GetPageCount(value);
// Removes unused buffers if decreasing stream length
while (currentPageCount > neededPageCount)
_streamBuffers[--currentPageCount] = null;
AllocSpaceIfNeeded(value);
if (_position > (_length = value))
_position = _length;
}
public override void Write(byte[] buffer, int offset, int count)
{
int currentPage = (int)(_position / PAGE_SIZE);
int currentOffset = (int)(_position % PAGE_SIZE);
int currentLength = PAGE_SIZE - currentOffset;
long startPosition = _position;
AllocSpaceIfNeeded(_position + count);
while (count != 0)
{
if (currentLength > count)
currentLength = count;
Array.Copy(buffer, offset, _streamBuffers[currentPage++], currentOffset, currentLength);
offset += currentLength;
_position += currentLength;
count -= currentLength;
currentOffset = 0;
currentLength = PAGE_SIZE;
}
}
#endregion Stream
}
2- or just push the file to the clients by simply returning the file from HDD (this might be slow if you want faster transfer use better storage units or move them to the blazing fast RAM..) through the controller and to the view.
using this specific return type:
return new PhysicalFileResult("Directory Containing File",
"application/octet-stream")
{ FileDownloadName = "Your file name + extension, for example: test.txt or test.zip etc.." };
It was pain in the ass but worth it since no one is really answering this question online :)
Trying to return items > 2GB from the same I/O call is never gonna end well. At no point ever do you want a single byte[] with then entire contents of the item. Instead, when working with such large items you want to get a stream, where you can read and buffer only small segments at a time. You can use WebClient.GetWebRequest() and WebClient.GetWebResponse() to accomplish this.

ARC4 encryption not working correctly server side

I have a socket.io client which sends data to each other where encryption is based on ARC4.
I tried multiple different scenarios but it keeps failing to decrypt anything and I'm not sure why.
The class: ARC4_New
public class ARC4_New
{
private int i;
private int j;
private byte[] bytes;
public const int POOLSIZE = 256;
public ARC4_New()
{
bytes = new byte[POOLSIZE];
}
public ARC4_New(byte[] key)
{
bytes = new byte[POOLSIZE];
this.Initialize(key);
}
public void Initialize(byte[] key)
{
this.i = 0;
this.j = 0;
for (i = 0; i < POOLSIZE; ++i)
{
this.bytes[i] = (byte)i;
}
for (i = 0; i < POOLSIZE; ++i)
{
j = (j + bytes[i] + key[i % key.Length]) & (POOLSIZE - 1);
this.Swap(i, j);
}
this.i = 0;
this.j = 0;
}
private void Swap(int a, int b)
{
byte t = this.bytes[a];
this.bytes[a] = this.bytes[b];
this.bytes[b] = t;
}
public byte Next()
{
this.i = ++this.i & (POOLSIZE - 1);
this.j = (this.j + this.bytes[i]) & (POOLSIZE - 1);
this.Swap(i, j);
return this.bytes[(this.bytes[i] + this.bytes[j]) & 255];
}
public void Encrypt(ref byte[] src)
{
for (int k = 0; k < src.Length; k++)
{
src[k] ^= this.Next();
}
}
public void Decrypt(ref byte[] src)
{
this.Encrypt(ref src);
}
}
public System.Numerics.BigInteger RandomInteger(int bitSize)
{
var integerData = new byte[bitSize / 8];
_numberGenerator.NextBytes(integerData);
integerData[integerData.Length - 1] &= 0x7f;
return new System.Numerics.BigInteger(integerData);
}
My script which generates a key:
System.Numerics.BigInteger DHPrivate = RandomInteger(256);
System.Numerics.BigInteger DHPrimal = RandomInteger(256);
System.Numerics.BigInteger DHGenerated = RandomInteger(256);
if (DHGenerated > DHPrimal)
{
System.Numerics.BigInteger tempG = DHGenerated;
DHGenerated= DHPrimal;
DHPrimal = tempG;
}
Then with those values I generate a public key:
System.Numerics.BigInteger DHPublic = System.Numerics.BigInteger.ModPow(DHGenerated, DHPrivate, DHPrimal);
Then I encrypt this key:
string pkey = EncryptY(CalculatePublic, DHPublic);
(Additional code for the encryption below)
protected virtual string EncryptY(Func<System.Numerics.BigInteger, System.Numerics.BigInteger> calculator, System.Numerics.BigInteger value)
{
byte[] valueData = Encoding.UTF8.GetBytes(value.ToString());
valueData = PKCSPad(valueData);
Array.Reverse(valueData);
var paddedInteger = new System.Numerics.BigInteger(valueData);
System.Numerics.BigInteger calculatedInteger = calculator(paddedInteger);
byte[] paddedData = calculatedInteger.ToByteArray();
Array.Reverse(paddedData);
string encryptedValue = Utils.Converter.BytesToHexString(paddedData).ToLower();
return encryptedValue.StartsWith("00") ? encryptedValue.Substring(2) : encryptedValue;
}
protected virtual byte[] PKCSPad(byte[] data)
{
var buffer = new byte[128 - 1];
int dataStartPos = (buffer.Length - data.Length);
buffer[0] = (byte)Padding;
Buffer.BlockCopy(data, 0, buffer, dataStartPos, data.Length);
int paddingEndPos = (dataStartPos - 1);
bool isRandom = (Padding == PKCSPadding.RandomByte);
for (int i = 1; i < paddingEndPos; i++)
{
buffer[i] = (byte)(isRandom ?
_numberGenerator.Next(1, 256) : byte.MaxValue);
}
return buffer;
}
After all that I sent the string PKEY to the server.
And after decrypting the string, the server gets the public key which is for example: 127458393
When I connect both my client and server using: 127458393
Like:
BigInteger key = System.Numerics.BigInteger.Parse("127458393");
client = new ARC4_New(PrimalDing.ToByteArray());
My client sends a string like:
client.Encrypt(BYTE_HERE);
And my server reads it like:
client.Decrypt(BYTE_HERE);
But it fails, and gets a random unreadable string.
What am I doing wrong here?
I managed to fix the issue
For some reason, my server was and is reversing the bytes i used in the ARC4 client..
So i simple reverse it now as a hotfix
System.Numerics.BigInteger temp = System.Numerics.BigInteger.Parse(textBox1.Text);
client = new ARC4_New(temp.ToByteArray().Reverse().ToArray());

Getting Error on Readprocessememory on c#

private static int FindPattern(byte[] Pattern)
{
Process[] P = Process.GetProcessesByName("example");
if (P.Length == 0)
{
return -1;
}
if (modules == exmaple())
{
modules = P[0].MainModule.BaseAddress;
}
byte[] _Buffer = new byte[268435457];
var tempVar = 0;
ReadProcessMemory(P[0].Handle, modules, out _Buffer, _Buffer.Length, ref tempVar);
int[] sBytes = new int[256];
int Len = Pattern.Length - 1;
var Dex = 0;
for (int i = 255; i >= 0; i--)
{
sBytes[i] = Pattern.Length;
}
for (int i = Len; i >= 0; i--)
{
sBytes[Pattern[i]] = Len;
}
while (Dex <= _Buffer.Length - Pattern.Length)
{
int i = Len;
while (_Buffer[Dex + i] == Pattern[i])
{
if (i == 0)
{
return Dex;
}
i -= 1;
}
Dex += sBytes[_Buffer[Dex + Len]];
}
return -1;
}
i tried a lot but i can't fix it.What did i did wrong?.
i am getting errors on this.Can anyone fix it for me please :
ReadProcessMemory(P[0].Handle, modules, out _Buffer, _Buffer.Length, ref tempVar);
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication81
{
class Program
{
[DllImport("kernel32.dll", SetLastError=true)]
static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,[Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
const int SIZE = 268435457;
static void Main(string[] args)
{
Process[] P = Process.GetProcessesByName("example");
if (P.Length == 0)
{
return -1;
}
if (modules == exmaple())
{
modules = P[0].MainModule.BaseAddress;
}
IntPtr buffer = Marshal.AllocHGlobal(SIZE);
var tempVar = 0;
ReadProcessMemory(P[0].Handle, modules, out buffer, SIZE, ref tempVar);
byte[] _Buffer = new byte[SIZE];
Marshal.PtrToStructure(buffer, _Buffer);
int[] sBytes = new int[256];
int Len = Pattern.Length - 1;
var Dex = 0;
for (int i = 255; i >= 0; i--)
{
sBytes[i] = Pattern.Length;
}
for (int i = Len; i >= 0; i--)
{
sBytes[Pattern[i]] = Len;
}
while (Dex <= _Buffer.Length - Pattern.Length)
{
int i = Len;
while (_Buffer[Dex + i] == Pattern[i])
{
if (i == 0)
{
return Dex;
}
i -= 1;
}
Dex += sBytes[_Buffer[Dex + Len]];
}
return -1;
}
}
}

AES to return Alphanumeric

I have an aes encryption code, i want to make it only return alphanumerical characters like {0123456789ABCDEFGHIJKLMNOPQRSTWUVYZ}
But however i could not figure out how to do that. I have almost no idea about encryption, could not figure out where to fix. I would really apreciate your feedback. Regards...
public class clsCrypto
{
private string _KEY = string.Empty;
protected internal string KEY
{
get
{
return _KEY;
}
set
{
if (!string.IsNullOrEmpty(value))
{
_KEY = value;
}
}
}
private string _IV = string.Empty;
protected internal string IV
{
get
{
return _IV;
}
set
{
if (!string.IsNullOrEmpty(value))
{
_IV = value;
}
}
}
private string CalcMD5(string strInput)
{
string strOutput = string.Empty;
if (!string.IsNullOrEmpty(strInput))
{
try
{
StringBuilder strHex = new StringBuilder();
using (MD5 md5 = MD5.Create())
{
byte[] bytArText = Encoding.Default.GetBytes(strInput);
byte[] bytArHash = md5.ComputeHash(bytArText);
for (int i = 0; i < bytArHash.Length; i++)
{
strHex.Append(bytArHash[i].ToString("X2"));
}
strOutput = strHex.ToString();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
return strOutput;
}
private byte[] GetBytesFromHexString(string strInput)
{
byte[] bytArOutput = new byte[] { };
if ((!string.IsNullOrEmpty(strInput)) && strInput.Length % 2 == 0)
{
SoapHexBinary hexBinary = null;
try
{
hexBinary = SoapHexBinary.Parse(strInput);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
bytArOutput = hexBinary.Value;
}
return bytArOutput;
}
private byte[] GenerateIV()
{
byte[] bytArOutput = new byte[] { };
try
{
string strIV = CalcMD5(IV);
bytArOutput = GetBytesFromHexString(strIV);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return bytArOutput;
}
private byte[] GenerateKey()
{
byte[] bytArOutput = new byte[] { };
try
{
string strKey = CalcMD5(KEY);
bytArOutput = GetBytesFromHexString(strKey);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return bytArOutput;
}
protected internal string Encrypt(string strInput, CipherMode cipherMode)
{
string strOutput = string.Empty;
if (!string.IsNullOrEmpty(strInput))
{
try
{
byte[] bytePlainText = Encoding.Default.GetBytes(strInput);
using (RijndaelManaged rijManaged = new RijndaelManaged())
{
rijManaged.Mode = cipherMode;
rijManaged.BlockSize = 128;
rijManaged.KeySize = 128;
rijManaged.IV = GenerateIV();
rijManaged.Key = GenerateKey();
rijManaged.Padding = PaddingMode.Zeros;
ICryptoTransform icpoTransform = rijManaged.CreateEncryptor(rijManaged.Key, rijManaged.IV);
using (MemoryStream memStream = new MemoryStream())
{
using (CryptoStream cpoStream = new CryptoStream(memStream, icpoTransform, CryptoStreamMode.Write))
{
cpoStream.Write(bytePlainText, 0, bytePlainText.Length);
cpoStream.FlushFinalBlock();
}
strOutput = Encoding.Default.GetString(memStream.ToArray());
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
return strOutput;
}
protected internal string Decrypt(string strInput, CipherMode cipherMode)
{
string strOutput = string.Empty;
if (!string.IsNullOrEmpty(strInput))
{
try
{
byte[] byteCipherText = Encoding.Default.GetBytes(strInput);
byte[] byteBuffer = new byte[strInput.Length];
using (RijndaelManaged rijManaged = new RijndaelManaged())
{
rijManaged.Mode = cipherMode;
rijManaged.BlockSize = 128;
rijManaged.KeySize = 128;
rijManaged.IV = GenerateIV();
rijManaged.Key = GenerateKey();
rijManaged.Padding = PaddingMode.Zeros;
ICryptoTransform icpoTransform = rijManaged.CreateDecryptor(rijManaged.Key, rijManaged.IV);
using (MemoryStream memStream = new MemoryStream(byteCipherText))
{
using (CryptoStream cpoStream = new CryptoStream(memStream, icpoTransform, CryptoStreamMode.Read))
{
cpoStream.Read(byteBuffer, 0, byteBuffer.Length);
}
strOutput = Encoding.Default.GetString(byteBuffer);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
return strOutput;
}
}
Encryption and decryption functions use byte arrays as parameters.
So, you must convert these arrays to base 36 string.
You can use the following class (Base36) to make these conversions:
All you have to do, is calling these two functions:
byte[] byteArray;
//To convert byte array to String
string byteArrayInBase36 = Base36.ByteArrayToBase36String(byteArray);
//To convert String to byte Array
byte[] byteArray2 = Base36.Base36StringToByteArray(byteArrayInBase36);
and, this is the class:
using System;
using System.Collections.Generic;
class Base36
{
#region public methods
public static string ByteArrayToBase36String(byte[] bytes)
{
string result = string.Empty;
result = Encode36((ulong)bytes.Length).PadLeft(BASE36_LENGTH_BLOC_SIZE_36, '0');
if (bytes.Length > 0)
{
List<byte[]> byteslist = SplitBytes(bytes, 8);
if (byteslist[byteslist.Count - 1].Length < 8)
{
byte[] newLastArray = new byte[8];
byteslist[byteslist.Count - 1].CopyTo(newLastArray, 0);
byteslist[byteslist.Count - 1] = newLastArray;
}
foreach (byte[] byteArray in byteslist)
{
ulong value = 0;
//for (int i = 0; i < byteArray.Length; i++) value = value * 256 + byteArray[i];
value = BitConverter.ToUInt64(byteArray, 0);
result = result + Encode36(value).PadLeft(BASE36_BLOC_SIZE_36, '0');
}
}
return result;
}
public static byte[] Base36StringToByteArray(string input)
{
byte[] result = new byte[0];
if (input.Length >= BASE36_LENGTH_BLOC_SIZE_36)
{
int arrayLength = (int)Decode36(input.Substring(0, BASE36_LENGTH_BLOC_SIZE_36));
string data = input.Remove(0, BASE36_LENGTH_BLOC_SIZE_36);
List<byte[]> bytesList = new List<byte[]>();
foreach (string value36 in new List<string>(SplitStringByLength(data, BASE36_BLOC_SIZE_36)))
{
byte[] byteArray = BitConverter.GetBytes(Decode36(value36));
bytesList.Add(byteArray);
}
result = JoinBytes(bytesList);
Array.Resize(ref result, arrayLength);
}
return result;
}
#endregion
#region Const
private const int BASE36_LENGTH_BLOC_SIZE_36 = 6;
private const int BASE36_BLOC_SIZE_36 = 13; //Encode36(ulong.MaxValue).Length;
#endregion
#region private methods
static string _CharList36 = string.Empty;
static private string CharList36
{
get
{
if (_CharList36.Length < 36)
{
char[] array = new char[36];
for (int i = 0; i < 10; i++) array[i] = (char)(i + 48);
for (int i = 0; i < 26; i++) array[i + 10] = (char)(i + 97);
_CharList36 = new string(array);
}
return _CharList36;
}
}
private static List<string> SplitStringByLength(string str, int chunkSize)
{
List<string> list = new List<string>();
int i;
for (i = 0; i < str.Length / chunkSize; i++)
{
list.Add(str.Substring(i * chunkSize, chunkSize));
}
i = i * chunkSize;
if (i < str.Length - 1)
list.Add(str.Substring(i, str.Length - i));
return list;
}
private static String Encode36(ulong input)
{
if (input < 0) throw new ArgumentOutOfRangeException("input", input, "input cannot be negative");
char[] clistarr = CharList36.ToCharArray();
var result = new Stack<char>();
while (input != 0)
{
result.Push(clistarr[input % 36]);
input /= 36;
}
return new string(result.ToArray()).ToUpper();
}
private static ulong Decode36(string input)
{
var reversed = ReverseString(input.ToLower());
ulong result = 0;
int pos = 0;
foreach (char c in reversed)
{
result += (ulong)CharList36.IndexOf(c) * (ulong)Math.Pow(36, pos);
pos++;
}
return result;
}
private static string ReverseString(string text)
{
char[] cArray = text.ToCharArray();
string reverse = String.Empty;
for (int i = 0; i < cArray.Length / 2; i++)
{
char c = cArray[i];
cArray[i] = cArray[cArray.Length - 1 - i];
cArray[cArray.Length - 1 - i] = c;
}
return new string(cArray);
}
private static byte[] StringToBytes(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
private static List<byte[]> SplitBytes(byte[] bytes, int length)
{
List<byte[]> result = new List<byte[]>();
int position = 0;
while (bytes.Length - position > length)
{
byte[] temp = new byte[length];
for (int i = 0; i < temp.Length; i++) temp[i] = bytes[i + position];
position += length;
result.Add(temp);
}
if (position < bytes.Length)
{
byte[] temp = new byte[bytes.Length - position];
for (int i = 0; i + position < bytes.Length; i++) temp[i] = bytes[i + position];
result.Add(temp);
}
return result;
}
private static string BytesToString(byte[] bytes)
{
char[] chars = new char[bytes.Length / sizeof(char)];
System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
return new string(chars);
}
private static byte[] JoinBytes(List<byte[]> listBytes)
{
int totalLength = 0;
foreach (byte[] bytes in listBytes) totalLength += bytes.Length;
byte[] result = new byte[totalLength];
int position = 0;
foreach (byte[] bytes in listBytes)
for (int i = 0; i < bytes.Length; i++)
{
result[position] = bytes[i];
position++;
}
return result;
}
#endregion
}
You can encode the resulting bytes using Base36 or another such binary-to-text encoding.

What is the C# equivalent of BitSet of Java?

My requirements are simple:
Be able to define dimensions of bit array, i.e: 5 bytes.
bool Get(bitIndex: int)
Set(bitIndex: int)
Is there a c# equivalent which provides similar functionality to BitSet in Java?
Here's the scenario:
Initialize 5 bytes, all bits are 0(false).
Set byte 3, bit 8 to TRUE.
Get status of byte 3, bit 8.
UPDATE: Solution from Michael Bray:
static void Main(string[] args)
{
// Set for 5 bytes
BitArray ba = new BitArray(8 * 5);
// Set bit #1 on byte #4
ba.Set(GetBitNum(4, 1), true);
// Get bit #1 on byte #4
bool v = ba.Get(GetBitNum(4, 1));
}
static int GetBitNum(int byteNum, int bitNum) // Assumes index starts at 1
{
return (byteNum - 1) * 8 + (bitNum - 1);
}
System.Collections.BitArray is pretty close, but it's a bit lacking in features. I wrote a helper class that implements a lot of features you might need for BitArray some time ago, but I'd have to dig it up. Let me know if you think you need it.
EDIT: As requested in the comments below, I've posted the code at http://pastebin.com/GLyzcUZC. As I discuss, though, it's benefits over stock BitArray are minimal, as I wrote it for some specific needs that I had. Do with it as you wish.
EDIT 2: As Miguel pointed out in the comments, there are some implementation issues that make my 'BitArray' code not so good... I had already realized the deficiencies and had re-written a new version called BoolArray (to distinguish from BitArray) that doesn't suffer from those problems :
namespace Utils
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Threading;
/// <summary>
/// A replacement for BitArray
/// </summary>
public class BoolArray : IEnumerable, ICollection, ICloneable
{
private UInt32[] bits = null;
private int _length = 0;
private static UInt32 ONE = (UInt32)1 << 31;
private object _syncRoot;
private static Func<byte[], byte[]> EndianFixer = null;
#region Constructors
static BoolArray()
{
if (BitConverter.IsLittleEndian) EndianFixer = (a) => a.Reverse().ToArray();
else EndianFixer = (a) => a;
}
public BoolArray(BoolArray srcBits)
{
this.InitializeFrom(srcBits.ToArray());
}
public BoolArray(BitArray srcBits)
{
this._length = srcBits.Count;
this.bits = new UInt32[RequiredSize(this._length)];
for (int i = 0; i < srcBits.Count; i++) this[i] = srcBits[i];
}
public BoolArray(int v)
{
ICollection<byte> bytes = EndianFixer(BitConverter.GetBytes(v)).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<bool> srcBits)
{
this.InitializeFrom(srcBits.ToArray());
}
public BoolArray(ICollection<byte> srcBits)
{
InitializeFrom(srcBits);
}
public BoolArray(ICollection<short> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<ushort> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<int> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<uint> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<long> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(ICollection<ulong> srcBits)
{
ICollection<byte> bytes = srcBits.SelectMany(v => EndianFixer(BitConverter.GetBytes(v))).ToList();
InitializeFrom(bytes);
}
public BoolArray(int capacity, bool defaultValue = false)
{
this.bits = new UInt32[RequiredSize(capacity)];
this._length = capacity;
// Only need to do this if true, because default for all bits is false
if (defaultValue) for (int i = 0; i < this._length; i++) this[i] = true;
}
private void InitializeFrom(ICollection<byte> srcBits)
{
this._length = srcBits.Count * 8;
this.bits = new UInt32[RequiredSize(this._length)];
for (int i = 0; i < srcBits.Count; i++)
{
uint bv = srcBits.Skip(i).Take(1).Single();
for (int b = 0; b < 8; b++)
{
bool bitVal = ((bv << b) & 0x0080) != 0;
int bi = 8 * i + b;
this[bi] = bitVal;
}
}
}
private void InitializeFrom(ICollection<bool> srcBits)
{
this._length = srcBits.Count;
this.bits = new UInt32[RequiredSize(this._length)];
int index = 0;
foreach (var b in srcBits) this[index++] = b;
}
private static int RequiredSize(int bitCapacity)
{
return (bitCapacity + 31) >> 5;
}
#endregion
public bool this[int index]
{
get
{
if (index >= _length) throw new IndexOutOfRangeException();
int byteIndex = index >> 5;
int bitIndex = index & 0x1f;
return ((bits[byteIndex] << bitIndex) & ONE) != 0;
}
set
{
if (index >= _length) throw new IndexOutOfRangeException();
int byteIndex = index >> 5;
int bitIndex = index & 0x1f;
if (value) bits[byteIndex] |= (ONE >> bitIndex);
else bits[byteIndex] &= ~(ONE >> bitIndex);
}
}
#region Interfaces implementation
#region IEnumerable
public IEnumerator GetEnumerator()
{
//for (int i = 0; i < _length; i++) yield return this[i];
return this.ToArray().GetEnumerator();
}
#endregion
#region ICollection
public void CopyTo(Array array, int index)
{
if (array == null) throw new ArgumentNullException("array");
if (index < 0) throw new ArgumentOutOfRangeException("index");
if (array.Rank != 1) throw new ArgumentException("Multidimensional array not supported");
if (array is UInt32[]) Array.Copy(this.bits, 0, array, index, (this.Count + sizeof(UInt32) - 1) / sizeof(UInt32));
else if (array is bool[]) Array.Copy(this.ToArray(), 0, array, index, this.Count);
else throw new ArgumentException("Array type not supported (UInt32[] or bool[] only)");
}
public int Count
{
get { return this._length; }
private set
{
if (value > this._length) Extend(value - this._length);
else this._length = Math.Max(0, value);
}
}
public bool IsSynchronized
{
get { return false; }
}
public object SyncRoot
{
get
{
if (this._syncRoot == null) Interlocked.CompareExchange<object>(ref this._syncRoot, new object(), null);
return _syncRoot;
}
}
#endregion
#region ICloneable
public object Clone()
{
return new BoolArray(this);
}
// Not part of ICloneable, but better - returns a strongly-typed result
public BoolArray Dup()
{
return new BoolArray(this);
}
#endregion
#endregion
#region String Conversions
public override string ToString()
{
return ToBinaryString();
//return ToHexString(" ", " ■ ");
}
public static BoolArray FromHexString(string hex)
{
if (hex == null) throw new ArgumentNullException("hex");
List<bool> bits = new List<bool>();
for (int i = 0; i < hex.Length; i++)
{
int b = byte.Parse(hex[i].ToString(), NumberStyles.HexNumber);
bits.Add((b >> 3) == 1);
bits.Add(((b & 0x7) >> 2) == 1);
bits.Add(((b & 0x3) >> 1) == 1);
bits.Add((b & 0x1) == 1);
}
BoolArray ba = new BoolArray(bits.ToArray());
return ba;
}
public string ToHexString(string bitSep8 = null, string bitSep128 = null)
{
string s = string.Empty;
int b = 0;
bool[] bbits = this.ToArray();
for (int i = 1; i <= bbits.Length; i++)
{
b = (b << 1) | (bbits[i - 1] ? 1 : 0);
if (i % 4 == 0)
{
s = s + string.Format("{0:x}", b);
b = 0;
}
if (i % (8 * 16) == 0)
{
s = s + bitSep128;
}
else if (i % 8 == 0)
{
s = s + bitSep8;
}
}
int ebits = bbits.Length % 4;
if (ebits != 0)
{
b = b << (4 - ebits);
s = s + string.Format("{0:x}", b);
}
return s;
}
public static BoolArray FromBinaryString(string bin, char[] trueChars = null)
{
if (trueChars == null) trueChars = new char[] { '1', 'Y', 'y', 'T', 't' };
if (bin == null) throw new ArgumentNullException("bin");
BoolArray ba = new BoolArray(bin.Length);
for (int i = 0; i < bin.Length; i++) ba[i] = bin[i].In(trueChars);
return ba;
}
public string ToBinaryString(char setChar = '1', char unsetChar = '0')
{
return new string(this.ToArray().Select(v => v ? setChar : unsetChar).ToArray());
}
#endregion
#region Class Methods
public bool[] ToArray()
{
bool[] vbits = new bool[this._length];
for (int i = 0; i < _length; i++) vbits[i] = this[i];
return vbits;
}
public BoolArray Append(ICollection<bool> addBits)
{
int startPos = this._length;
Extend(addBits.Count);
bool[] bitArray = addBits.ToArray();
for (int i = 0; i < bitArray.Length; i++) this[i + startPos] = bitArray[i];
return this;
}
public BoolArray Append(BoolArray addBits)
{
return this.Append(addBits.ToArray());
}
public static BoolArray Concatenate(params BoolArray[] bArrays)
{
return new BoolArray(bArrays.SelectMany(ba => ba.ToArray()).ToArray());
}
private void Extend(int numBits)
{
numBits += this._length;
int reqBytes = RequiredSize(numBits);
if (reqBytes > this.bits.Length)
{
UInt32[] newBits = new UInt32[reqBytes];
this.bits.CopyTo(newBits, 0);
this.bits = newBits;
}
this._length = numBits;
}
public bool Get(int index)
{
return this[index];
}
public BoolArray GetBits(int startBit = 0, int numBits = -1)
{
if (numBits == -1) numBits = bits.Length;
return new BoolArray(this.ToArray().Skip(startBit).Take(numBits).ToArray());
}
public BoolArray Repeat(int numReps)
{
bool[] oBits = this.ToArray();
List<bool> nBits = new List<bool>();
for(int i=0; i<numReps; i++) nBits.AddRange(oBits);
this.InitializeFrom(nBits);
return this;
}
public BoolArray Reverse()
{
int n = this.Count;
for(int i=0; i<n/2; i++)
{
bool b1 = this[i];
this[i] = this[n - i - 1];
this[n - i - 1] = b1;
}
return this;
}
public BoolArray Set(int index, bool v)
{
this[index] = v;
return this;
}
public BoolArray SetAll(bool v)
{
for (int i = 0; i < this.Count; i++) this[i] = v;
return this;
}
public BoolArray SetBits(ICollection<bool> setBits, int destStartBit = 0, int srcStartBit = 0, int numBits = -1, bool allowExtend = false)
{
if (setBits == null) throw new ArgumentNullException("setBits");
if ((destStartBit < 0) || (destStartBit >= this.Count)) throw new ArgumentOutOfRangeException("destStartBit");
if ((srcStartBit < 0) || (srcStartBit >= setBits.Count)) throw new ArgumentOutOfRangeException("srcStartBit");
bool[] sBits;
if (setBits is bool[]) sBits = (bool[])setBits;
else sBits = setBits.ToArray();
if (numBits == -1) numBits = setBits.Count;
if (numBits > (setBits.Count - srcStartBit)) numBits = setBits.Count - srcStartBit;
int diffSize = numBits - (this.Count - destStartBit);
if (diffSize > 0)
{
if (allowExtend) Extend(diffSize);
else numBits = this.Count - destStartBit;
}
for (int i = 0; i < numBits; i++) this[destStartBit + i] = sBits[srcStartBit + i];
return this;
}
public List<BoolArray> SplitEvery(int numBits)
{
int i = 0;
List<BoolArray> bitSplits = new List<BoolArray>();
while (i < this.Count)
{
bitSplits.Add(this.GetBits(i, numBits));
i += numBits;
}
return bitSplits;
}
public byte[] ToBytes(int startBit = 0, int numBits = -1)
{
if (numBits == -1) numBits = this._length - startBit;
BoolArray ba = GetBits(startBit, numBits);
int nb = (numBits + 7) / 8;
byte[] bb = new byte[nb];
for (int i = 0; i < ba.Count; i++)
{
if (!ba[i]) continue;
int bp = 7 - (i % 8);
bb[i / 8] = (byte)((int)bb[i / 8] | (1 << bp));
}
return bb;
}
#endregion
#region Logical Bitwise Operations
public BoolArray BinaryBitwiseOp(Func<bool, bool, bool> op, BoolArray ba, int start = 0)
{
for (int i = 0; i < ba.Count; i++)
{
if (start + i >= this.Count) break;
this[start + i] = op(this[start + i], ba[i]);
}
return this;
}
public BoolArray Xor(BoolArray xor, int start = 0)
{
return BinaryBitwiseOp((a, b) => (a ^ b), xor, start);
}
public BoolArray And(BoolArray and, int start = 0)
{
return BinaryBitwiseOp((a, b) => (a & b), and, start);
}
public BoolArray Or(BoolArray or, int start = 0)
{
return BinaryBitwiseOp((a, b) => (a | b), or, start);
}
public BoolArray Not(int start = 0, int len = -1)
{
for (int i = start; i < this.Count; i++)
{
if (--len == -1) break;
this[i] = !this[i];
}
return this;
}
#endregion
#region Class Operators
public static BoolArray operator +(BoolArray a, BoolArray b)
{
return a.Dup().Append(b);
}
public static BoolArray operator |(BoolArray a, BoolArray b)
{
return a.Dup().Or(b);
}
public static BoolArray operator &(BoolArray a, BoolArray b)
{
return a.Dup().And(b);
}
public static BoolArray operator ^(BoolArray a, BoolArray b)
{
return a.Dup().Xor(b);
}
public static BoolArray operator ~(BoolArray a)
{
return a.Dup().Not();
}
public static BoolArray operator <<(BoolArray a, int shift)
{
return a.Dup().Append(new bool[shift]);
}
public static BoolArray operator >>(BoolArray a, int shift)
{
return new BoolArray(a.ToArray().Take(Math.Max(0, a.Count - shift)).ToArray());
}
public static bool operator ==(BoolArray a, BoolArray b)
{
if (a.Count != b.Count) return false;
for (int i = 0; i < a.Count; i++) if (a[i] != b[i]) return false;
return true;
}
public override bool Equals(object obj)
{
if (!(obj is BoolArray)) return false;
return (this == (BoolArray)obj);
}
public override int GetHashCode()
{
return this.ToHexString().GetHashCode();
}
public static bool operator !=(BoolArray a, BoolArray b)
{
return !(a == b);
}
#endregion
}
}
I had the same issue, but had more than just the one Cardinality method to convert. So, I opted to port the entire BitSet class. Fortunately it was self-contained.
Here is the Gist of the C# port.
I have also added it to the open source BoboBrowse.Net project.
I have also ported the version from Apache Harmony (which is essentially a carbon copy of the JDK) and added it to the general library J2N so it is easy to consume.

Categories

Resources